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