tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: KAUTH_GENERIC_CANSEE



Forgot the diff...

-e.
Index: init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.170
diff -u -p -r1.170 init_sysctl.c
--- init_sysctl.c       12 Dec 2009 17:29:34 -0000      1.170
+++ init_sysctl.c       23 Dec 2009 02:05:09 -0000
@@ -96,6 +96,9 @@ uid_t security_setidcore_owner = 0;
 gid_t security_setidcore_group = 0;
 mode_t security_setidcore_mode = (S_IRUSR|S_IWUSR);
 
+/* Initialized in sysctl_init() for now... */
+/* static */ kmutex_t sysctl_file_marker;
+
 static const u_int sysctl_flagmap[] = {
        PK_ADVLOCK, P_ADVLOCK,
        PK_EXEC, P_EXEC,
@@ -1871,13 +1874,48 @@ sysctl_kern_drivers(SYSCTLFN_ARGS)
 }
 
 /*
+ * Expects to be called with proc_lock and sysctl_file_marker locked.
+ */
+static void
+sysctl_file_marker_reset(void)
+{
+       struct proc *p;
+
+       PROCLIST_FOREACH(p, &allproc) {
+               struct filedesc *fd = p->p_fd;
+               fdtab_t *dt;
+               u_int i;
+
+               mutex_enter(&fd->fd_lock);
+
+               dt = fd->fd_dt;
+               for (i = 0; i < dt->dt_nfiles; i++) {
+                       struct file *fp;
+                       fdfile_t *ff;
+
+                       if ((ff = dt->dt_ff[i]) == NULL) {
+                               continue;
+                       }
+
+                       if ((fp = ff->ff_file) == NULL) {
+                               continue;
+                       }
+
+                       fp->f_unused1 = 0;
+               }
+
+               mutex_exit(&fd->fd_lock);
+       }
+}
+
+/*
  * sysctl helper function for kern.file2
  */
 static int
 sysctl_kern_file2(SYSCTLFN_ARGS)
 {
        struct proc *p;
-       struct file *fp, *tp, *np;
+       struct file *fp;
        struct filedesc *fd;
        struct kinfo_file kf;
        char *dp;
@@ -1886,6 +1924,7 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
        int error, arg, elem_count;
        fdfile_t *ff;
        fdtab_t *dt;
+       static u_int seq = 1;
 
        if (namelen == 1 && name[0] == CTL_QUERY)
                return (sysctl_query(SYSCTLFN_CALL(rnode)));
@@ -1908,66 +1947,24 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
 
        switch (op) {
        case KERN_FILE_BYFILE:
+       case KERN_FILE_BYPID:
                /*
-                * doesn't use arg so it must be zero
-                */
-               if (arg != 0)
-                       return (EINVAL);
-               sysctl_unlock();
-               /*
-                * allocate dummy file descriptor to make position in list
+                * We're traversing the process list in both cases; the BYFILE
+                * case does additional work of keeping track of files already
+                * looked at.
                 */
-               if ((tp = fgetdummy()) == NULL) {
-                       sysctl_relock();
-                       return ENOMEM;
-               }
-               mutex_enter(&filelist_lock);
-               for (fp = LIST_FIRST(&filehead); fp != NULL; fp = np) {
-                       np = LIST_NEXT(fp, f_list);
-                       mutex_enter(&fp->f_lock);
-                       if (fp->f_count == 0) {
-                               mutex_exit(&fp->f_lock);
-                               continue;
-                       }
-                       /*
-                        * XXX Need to prevent that from being an alternative
-                        * XXX way for getting process information.
-                        */
-                       if (kauth_authorize_generic(l->l_cred,
-                           KAUTH_GENERIC_CANSEE, fp->f_cred) != 0) {
-                               mutex_exit(&fp->f_lock);
-                               continue;
-                       }
-                       if (len >= elem_size && elem_count > 0) {
-                               fill_file(&kf, fp, NULL, 0, 0);
-                               LIST_INSERT_AFTER(fp, tp, f_list);
-                               mutex_exit(&fp->f_lock);
-                               mutex_exit(&filelist_lock);
-                               error = dcopyout(l, &kf, dp, out_size);
-                               mutex_enter(&filelist_lock);
-                               np = LIST_NEXT(tp, f_list);
-                               LIST_REMOVE(tp, f_list);
-                               if (error) {
-                                       break;
-                               }
-                               dp += elem_size;
-                               len -= elem_size;
-                       } else {
-                               mutex_exit(&fp->f_lock);
-                       }
-                       needed += elem_size;
-                       if (elem_count > 0 && elem_count != INT_MAX)
-                               elem_count--;
-               }
-               mutex_exit(&filelist_lock);
-               fputdummy(tp);
-               sysctl_relock();
-               break;
-       case KERN_FILE_BYPID:
-               if (arg < -1)
+
+               /* doesn't use arg so it must be zero */
+               if ((op == KERN_FILE_BYFILE) && (arg != 0))
+                       return EINVAL;
+
+               if ((op == KERN_FILE_BYPID) && (arg < -1))
                        /* -1 means all processes */
                        return (EINVAL);
+
                sysctl_unlock();
+               if (op == KERN_FILE_BYFILE)
+                       mutex_enter(&sysctl_file_marker);
                mutex_enter(proc_lock);
                PROCLIST_FOREACH(p, &allproc) {
                        if (p->p_stat == SIDL) {
@@ -2013,6 +2010,11 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
                                if ((fp = ff->ff_file) == NULL) {
                                        continue;
                                }
+
+                               if ((op == KERN_FILE_BYFILE) &&
+                                   (fp->f_unused1 == seq)) {
+                                       continue;
+                               }
                                if (len >= elem_size && elem_count > 0) {
                                        mutex_enter(&fp->f_lock);
                                        fill_file(&kf, fp, ff, i, p->p_pid);
@@ -2025,6 +2027,8 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
                                        dp += elem_size;
                                        len -= elem_size;
                                }
+                               if (op == KERN_FILE_BYFILE)
+                                       fp->f_unused1 = seq;
                                needed += elem_size;
                                if (elem_count > 0 && elem_count != INT_MAX)
                                        elem_count--;
@@ -2037,7 +2041,18 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
                        mutex_enter(proc_lock);
                        rw_exit(&p->p_reflock);
                }
+               if (op == KERN_FILE_BYFILE) {
+                       seq++;
+
+                       /* Reset all markers if wrapped. */
+                       if (seq == 0) {
+                               sysctl_file_marker_reset();
+                               seq++;
+                       }
+               }
                mutex_exit(proc_lock);
+               if (op == KERN_FILE_BYFILE)
+                       mutex_exit(&sysctl_file_marker);
                sysctl_relock();
                break;
        default:
Index: kern_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.226
diff -u -p -r1.226 kern_sysctl.c
--- kern_sysctl.c       16 Sep 2009 15:23:04 -0000      1.226
+++ kern_sysctl.c       23 Dec 2009 02:05:10 -0000
@@ -220,6 +220,7 @@ void
 sysctl_init(void)
 {
        sysctl_setup_func * const *sysctl_setup, f;
+       extern kmutex_t sysctl_file_marker; /* in init_sysctl.c */
 
        rw_init(&sysctl_treelock);
 
@@ -235,6 +236,8 @@ sysctl_init(void)
                f = (void*)*sysctl_setup;
                (*f)(NULL);
        }
+
+       mutex_init(&sysctl_file_marker, MUTEX_DEFAULT, IPL_NONE);
 }
 
 /*


Home | Main Index | Thread Index | Old Index