diff -Nru ifupdown-0.7~beta2ubuntu8/debian/changelog ifupdown-0.7~beta2ubuntu9~lp1160490/debian/changelog --- ifupdown-0.7~beta2ubuntu8/debian/changelog 2012-04-04 19:27:05.000000000 -0500 +++ ifupdown-0.7~beta2ubuntu9~lp1160490/debian/changelog 2013-08-20 16:50:00.000000000 -0500 @@ -1,3 +1,10 @@ +ifupdown (0.7~beta2ubuntu9) precise; urgency=low + + * Race condition updating statefile. (LP: #1160490) + http://anonscm.debian.org/hg/collab-maint/ifupdown/rev/a93db3ecb8f0 + + -- Chris J Arges Tue, 20 Aug 2013 16:49:46 -0500 + ifupdown (0.7~beta2ubuntu8) precise; urgency=low * Start networking upstart job on 'or container', to let us optimize the diff -Nru ifupdown-0.7~beta2ubuntu8/ifupdown.nw ifupdown-0.7~beta2ubuntu9~lp1160490/ifupdown.nw --- ifupdown-0.7~beta2ubuntu8/ifupdown.nw 2012-04-04 19:24:30.000000000 -0500 +++ ifupdown-0.7~beta2ubuntu9~lp1160490/ifupdown.nw 2013-08-20 16:49:29.000000000 -0500 @@ -3541,8 +3541,9 @@ <
>= int no_act = 0; int verbose = 0; -char *statefile = RUN_DIR "ifstate"; -char *tmpstatefile = RUN_DIR ".ifstate.tmp"; +char lockfile[] = RUN_DIR ".ifstate.lock"; +char statefile[] = RUN_DIR "ifstate"; +char tmpstatefile[] = RUN_DIR ".ifstate.tmp"; char *nm_system_settings = "/etc/NetworkManager/NetworkManager.conf"; @ @@ -4163,6 +4164,37 @@ static void update_state(const char *argv0, const char *iface, const char *liface); @ +<
>= +FILE * +lock_state (const char * argv0) +{ + FILE *lock_fp; + lock_fp = fopen(lockfile, no_act ? "r" : "a+"); + if (lock_fp == NULL) { + if (!no_act) { + fprintf(stderr, "%s: failed to open lockfile %s: %s\n", argv0, lockfile, strerror(errno)); + exit(1); + } else { + return NULL; + } + } + + int flags; + + if ((flags = fcntl(fileno(lock_fp), F_GETFD)) < 0 || fcntl(fileno(lock_fp), F_SETFD, flags | FD_CLOEXEC) < 0) { + fprintf(stderr, "%s: failed to set FD_CLOEXEC on lockfile %s: %s\n", argv0, lockfile, strerror(errno)); + exit(1); + } + + if (lock_fd(fileno(lock_fp)) < 0) { + fprintf(stderr, "%s: failed to lock lockfile %s: %s\n", argv0, lockfile, strerror(errno)); + exit(1); + } + + return lock_fp; +} +@ + The first of these functions reads the state file to look for an interface and returns the current state of it as a pointer to a static buffer which should be copied if it's needed for any duration. If the interface has no @@ -4307,10 +4339,13 @@ @ <>= +FILE *lock_fp; FILE *state_fp; char buf[80]; char *p; +lock_fp = lock_state(argv0); + state_fp = fopen(statefile, no_act ? "r" : "a+"); if (state_fp == NULL) { if (!no_act) { @@ -4333,13 +4368,6 @@ argv0, statefile, strerror(errno)); exit(1); } - - if (lock_fd (fileno(state_fp)) < 0) { - fprintf(stderr, - "%s: failed to lock statefile %s: %s\n", - argv0, statefile, strerror(errno)); - exit(1); - } } @ @@ -4360,6 +4388,10 @@ fclose(state_fp); state_fp = NULL; } +if (lock_fp != NULL) { + fclose(lock_fp); + lock_fp = NULL; +} @ This leaves our two useful chunks. The first checks to ensure what we're