summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2011-10-12 12:08:03 +0000
committerrwatson <rwatson@FreeBSD.org>2011-10-12 12:08:03 +0000
commit0a6da59b6136e874b57c98c59fd355951f60b93d (patch)
treed6695b8b83a264ff11acda471ca46cda4f4373f8 /sys/kern
parent69338c6aededc2f8d950c424cce3d41479115b8a (diff)
downloadFreeBSD-src-0a6da59b6136e874b57c98c59fd355951f60b93d.zip
FreeBSD-src-0a6da59b6136e874b57c98c59fd355951f60b93d.tar.gz
Correct a bug in export of capability-related information from the sysctls
supporting procstat -f: properly provide capability rights information to userspace. The bug resulted from a merge-o during upstreaming (or rather, a failure to properly merge FreeBSD-side changed downstream). Spotted by: des, kibab MFC after: 3 days
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index a2100e0..8b3e20e 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3182,7 +3182,8 @@ CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
static int
export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
- int64_t offset, struct kinfo_file *kif, struct sysctl_req *req)
+ int64_t offset, int fd_is_cap, cap_rights_t fd_cap_rights,
+ struct kinfo_file *kif, struct sysctl_req *req)
{
struct {
int fflag;
@@ -3243,6 +3244,10 @@ export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
for (i = 0; i < NFFLAGS; i++)
if (fflags & fflags_table[i].fflag)
kif->kf_flags |= fflags_table[i].kf_fflag;
+ if (fd_is_cap)
+ kif->kf_flags |= KF_FLAG_CAPABILITY;
+ if (fd_is_cap)
+ kif->kf_cap_rights = fd_cap_rights;
kif->kf_fd = fd;
kif->kf_type = type;
kif->kf_ref_count = refcnt;
@@ -3270,7 +3275,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
int64_t offset;
void *data;
int error, i, *name;
- int type, refcnt, fflags;
+ int fd_is_cap, type, refcnt, fflags;
+ cap_rights_t fd_cap_rights;
name = (int *)arg1;
if ((p = pfind((pid_t)name[0])) == NULL)
@@ -3299,13 +3305,13 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
if (tracevp != NULL)
export_fd_for_sysctl(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
- FREAD | FWRITE, -1, -1, kif, req);
+ FREAD | FWRITE, -1, -1, 0, 0, kif, req);
if (textvp != NULL)
export_fd_for_sysctl(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
- FREAD, -1, -1, kif, req);
+ FREAD, -1, -1, 0, 0, kif, req);
if (cttyvp != NULL)
export_fd_for_sysctl(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
- FREAD | FWRITE, -1, -1, kif, req);
+ FREAD | FWRITE, -1, -1, 0, 0, kif, req);
if (fdp == NULL)
goto fail;
FILEDESC_SLOCK(fdp);
@@ -3315,7 +3321,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
data = fdp->fd_cdir;
FILEDESC_SUNLOCK(fdp);
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
- FREAD, -1, -1, kif, req);
+ FREAD, -1, -1, 0, 0, kif, req);
FILEDESC_SLOCK(fdp);
}
/* root directory */
@@ -3324,7 +3330,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
data = fdp->fd_rdir;
FILEDESC_SUNLOCK(fdp);
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
- FREAD, -1, -1, kif, req);
+ FREAD, -1, -1, 0, 0, kif, req);
FILEDESC_SLOCK(fdp);
}
/* jail directory */
@@ -3333,13 +3339,15 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
data = fdp->fd_jdir;
FILEDESC_SUNLOCK(fdp);
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
- FREAD, -1, -1, kif, req);
+ FREAD, -1, -1, 0, 0, kif, req);
FILEDESC_SLOCK(fdp);
}
for (i = 0; i < fdp->fd_nfiles; i++) {
if ((fp = fdp->fd_ofiles[i]) == NULL)
continue;
data = NULL;
+ fd_is_cap = 0;
+ fd_cap_rights = 0;
#ifdef CAPABILITIES
/*
@@ -3348,8 +3356,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
* the capability rights mask.
*/
if (fp->f_type == DTYPE_CAPABILITY) {
- kif->kf_flags |= KF_FLAG_CAPABILITY;
- kif->kf_cap_rights = cap_rights(fp);
+ fd_is_cap = 1;
+ fd_cap_rights = cap_rights(fp);
(void)cap_funwrap(fp, 0, &fp);
}
#else /* !CAPABILITIES */
@@ -3428,8 +3436,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
oldidx = req->oldidx;
if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
FILEDESC_SUNLOCK(fdp);
- error = export_fd_for_sysctl(data, type, i,
- fflags, refcnt, offset, kif, req);
+ error = export_fd_for_sysctl(data, type, i, fflags, refcnt,
+ offset, fd_is_cap, fd_cap_rights, kif, req);
if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
FILEDESC_SLOCK(fdp);
if (error) {
OpenPOWER on IntegriCloud