diff options
author | kib <kib@FreeBSD.org> | 2011-08-16 20:07:47 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2011-08-16 20:07:47 +0000 |
commit | 011f42054d1f861cd2435866ba646fa0cf752103 (patch) | |
tree | 368bd0d481caa3081d9e36be04c87a458ccd8975 /sys/kern/uipc_mqueue.c | |
parent | a5a39a26b2ea8ab4d283505d58396a5e76d38c7a (diff) | |
download | FreeBSD-src-011f42054d1f861cd2435866ba646fa0cf752103.zip FreeBSD-src-011f42054d1f861cd2435866ba646fa0cf752103.tar.gz |
Add the fo_chown and fo_chmod methods to struct fileops and use them
to implement fchown(2) and fchmod(2) support for several file types
that previously lacked it. Add MAC entries for chown/chmod done on
posix shared memory and (old) in-kernel posix semaphores.
Based on the submission by: glebius
Reviewed by: rwatson
Approved by: re (bz)
Diffstat (limited to 'sys/kern/uipc_mqueue.c')
-rw-r--r-- | sys/kern/uipc_mqueue.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 0ca4161..fbd78c1 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2469,6 +2469,7 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, struct mqfs_node *pn = fp->f_data; bzero(st, sizeof *st); + sx_xlock(&mqfs_data.mi_lock); st->st_atim = pn->mn_atime; st->st_mtim = pn->mn_mtime; st->st_ctim = pn->mn_ctime; @@ -2476,10 +2477,56 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, st->st_uid = pn->mn_uid; st->st_gid = pn->mn_gid; st->st_mode = S_IFIFO | pn->mn_mode; + sx_xunlock(&mqfs_data.mi_lock); return (0); } static int +mqf_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, + struct thread *td) +{ + struct mqfs_node *pn; + int error; + + error = 0; + pn = fp->f_data; + sx_xlock(&mqfs_data.mi_lock); + error = vaccess(VREG, pn->mn_mode, pn->mn_uid, pn->mn_gid, VADMIN, + active_cred, NULL); + if (error != 0) + goto out; + pn->mn_mode = mode & ACCESSPERMS; +out: + sx_xunlock(&mqfs_data.mi_lock); + return (error); +} + +static int +mqf_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, + struct thread *td) +{ + struct mqfs_node *pn; + int error; + + error = 0; + pn = fp->f_data; + sx_xlock(&mqfs_data.mi_lock); + if (uid == (uid_t)-1) + uid = pn->mn_uid; + if (gid == (gid_t)-1) + gid = pn->mn_gid; + if (((uid != pn->mn_uid && uid != active_cred->cr_uid) || + (gid != pn->mn_gid && !groupmember(gid, active_cred))) && + (error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0))) + goto out; + pn->mn_uid = uid; + pn->mn_gid = gid; +out: + sx_xunlock(&mqfs_data.mi_lock); + return (error); +} + +static int mqf_kqfilter(struct file *fp, struct knote *kn) { struct mqueue *mq = FPTOMQ(fp); @@ -2535,6 +2582,8 @@ static struct fileops mqueueops = { .fo_poll = mqf_poll, .fo_kqfilter = mqf_kqfilter, .fo_stat = mqf_stat, + .fo_chmod = mqf_chmod, + .fo_chown = mqf_chown, .fo_close = mqf_close }; |