bsd_acct: plain current->real_parent access is not always safe
[sfrench/cifs-2.6.git] / kernel / acct.c
index 24f0f8b2ba724567861b6b8983b554f8f0473b90..7ff5339a3f058d50f3bbbdffcae8c8a38145ec19 100644 (file)
@@ -329,16 +329,16 @@ static comp_t encode_comp_t(unsigned long value)
        }
 
        /*
-         * If we need to round up, do it (and handle overflow correctly).
-         */
+        * If we need to round up, do it (and handle overflow correctly).
+        */
        if (rnd && (++value > MAXFRACT)) {
                value >>= EXPSIZE;
                exp++;
        }
 
        /*
-         * Clean it up and polish it off.
-         */
+        * Clean it up and polish it off.
+        */
        exp <<= MANTSIZE;               /* Shift the exponent into place */
        exp += value;                   /* and add on the mantissa. */
        return exp;
@@ -361,30 +361,30 @@ static comp_t encode_comp_t(unsigned long value)
 
 static comp2_t encode_comp2_t(u64 value)
 {
-        int exp, rnd;
-
-        exp = (value > (MAXFRACT2>>1));
-        rnd = 0;
-        while (value > MAXFRACT2) {
-                rnd = value & 1;
-                value >>= 1;
-                exp++;
-        }
-
-        /*
-         * If we need to round up, do it (and handle overflow correctly).
-         */
-        if (rnd && (++value > MAXFRACT2)) {
-                value >>= 1;
-                exp++;
-        }
-
-        if (exp > MAXEXP2) {
-                /* Overflow. Return largest representable number instead. */
-                return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
-        } else {
-                return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
-        }
+       int exp, rnd;
+
+       exp = (value > (MAXFRACT2>>1));
+       rnd = 0;
+       while (value > MAXFRACT2) {
+               rnd = value & 1;
+               value >>= 1;
+               exp++;
+       }
+
+       /*
+        * If we need to round up, do it (and handle overflow correctly).
+        */
+       if (rnd && (++value > MAXFRACT2)) {
+               value >>= 1;
+               exp++;
+       }
+
+       if (exp > MAXEXP2) {
+               /* Overflow. Return largest representable number instead. */
+               return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
+       } else {
+               return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
+       }
 }
 #endif
 
@@ -413,7 +413,7 @@ static u32 encode_float(u64 value)
  *  The acct_process() call is the workhorse of the process
  *  accounting system. The struct acct is built here and then written
  *  into the accounting file. This function should only be called from
- *  do_exit().
+ *  do_exit() or when switching to a different output file.
  */
 
 /*
@@ -482,7 +482,9 @@ static void do_acct_process(struct file *file)
 #endif
 #if ACCT_VERSION==3
        ac.ac_pid = current->tgid;
-       ac.ac_ppid = current->parent->tgid;
+       rcu_read_lock();
+       ac.ac_ppid = rcu_dereference(current->real_parent)->tgid;
+       rcu_read_unlock();
 #endif
 
        spin_lock_irq(&current->sighand->siglock);
@@ -501,14 +503,14 @@ static void do_acct_process(struct file *file)
        ac.ac_swaps = encode_comp_t(0);
 
        /*
-         * Kernel segment override to datasegment and write it
-         * to the accounting file.
-         */
+        * Kernel segment override to datasegment and write it
+        * to the accounting file.
+        */
        fs = get_fs();
        set_fs(KERNEL_DS);
        /*
-        * Accounting records are not subject to resource limits.
-        */
+        * Accounting records are not subject to resource limits.
+        */
        flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
        current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
        file->f_op->write(file, (char *)&ac,