diff -Nru ifupdown-0.7.2ubuntu2/debian/changelog ifupdown-0.7.2ubuntu3~lp1160490/debian/changelog --- ifupdown-0.7.2ubuntu2/debian/changelog 2012-10-09 10:13:28.000000000 -0500 +++ ifupdown-0.7.2ubuntu3~lp1160490/debian/changelog 2013-08-20 17:03:26.000000000 -0500 @@ -1,3 +1,10 @@ +ifupdown (0.7.2ubuntu3) quantal; 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:50:22 -0500 + ifupdown (0.7.2ubuntu2) quantal; urgency=low * Fix regression with the removal of the sysvinit networking job: diff -Nru ifupdown-0.7.2ubuntu2/ifupdown.nw ifupdown-0.7.2ubuntu3~lp1160490/ifupdown.nw --- ifupdown-0.7.2ubuntu2/ifupdown.nw 2012-09-12 15:33:58.000000000 -0500 +++ ifupdown-0.7.2ubuntu3~lp1160490/ifupdown.nw 2013-08-20 16:50:17.000000000 -0500 @@ -3634,8 +3634,9 @@ int no_act = 0; int run_scripts = 1; 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"; @ @@ -4398,6 +4399,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 @@ -4542,10 +4574,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) { @@ -4568,13 +4603,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); - } } @ @@ -4595,6 +4623,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