diff options
author | 1996-08-08 06:36:45 +0000 | |
---|---|---|
committer | 1996-08-08 06:36:45 +0000 | |
commit | 86d967db7ecd9da5e9e0d430000bcad2c0290a59 (patch) | |
tree | 0a91e01bdaf65f62d66e604f31a045480762b916 | |
parent | Disable RFC 1323 extensions by default (diff) | |
download | wireguard-openbsd-86d967db7ecd9da5e9e0d430000bcad2c0290a59.tar.xz wireguard-openbsd-86d967db7ecd9da5e9e0d430000bcad2c0290a59.zip |
Make {,f}chown(2) behaviour POSIX.1 compliant with SUID / SGID files
Enable CTL_FS processing by sysctl(3)
Add CTL_FS request to disable clearing SUID / SGID bit when a files owner
or group is changed by root
Make sysctl(8) understand CTL_FS requests
-rw-r--r-- | sbin/sysctl/sysctl.c | 41 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 54 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 42 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 24 | ||||
-rw-r--r-- | usr.sbin/sysctl/sysctl.c | 41 |
6 files changed, 181 insertions, 25 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index a5de0bd9ef8..c05b94f00bf 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -76,6 +76,7 @@ static char *rcsid = "$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $" struct ctlname topname[] = CTL_NAMES; struct ctlname kernname[] = CTL_KERN_NAMES; struct ctlname vmname[] = CTL_VM_NAMES; +struct ctlname fsname[] = CTL_FS_NAMES; struct ctlname netname[] = CTL_NET_NAMES; struct ctlname hwname[] = CTL_HW_NAMES; struct ctlname username[] = CTL_USER_NAMES; @@ -95,7 +96,7 @@ struct list secondlevel[] = { { 0, 0 }, /* CTL_UNSPEC */ { kernname, KERN_MAXID }, /* CTL_KERN */ { vmname, VM_MAXID }, /* CTL_VM */ - { 0, 0 }, /* CTL_FS */ + { fsname, FS_MAXID }, /* CTL_FS */ { netname, NET_MAXID }, /* CTL_NET */ { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ { hwname, HW_MAXID }, /* CTL_HW */ @@ -274,6 +275,12 @@ parse(string, flags) fprintf(stderr, "Use ps to view %s information\n", string); return; + case KERN_NTPTIME: + if (flags == 0) + return; + fprintf(stderr, + "Use xntpd to view %s information\n", string); + return; case KERN_CLOCKRATE: special |= CLOCK; break; @@ -328,6 +335,11 @@ parse(string, flags) break; case CTL_FS: + len = sysctl_fs(string, &bufp, mib, flags, &type); + if (len >= 0) + break; + return; + case CTL_USER: case CTL_DDB: break; @@ -484,6 +496,33 @@ debuginit() } } +struct ctlname posixname[] = CTL_FS_POSIX_NAMES; +struct list fslist = { posixname, FS_POSIX_MAXID }; + +/* + * handle file system requests + */ +sysctl_fs(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + if (*bufpp == NULL) { + listall(string, &fslist); + return (-1); + } + if ((indx = findname(string, "third", bufpp, &fslist)) == -1) + return (-1); + mib[2] = indx; + *typep = fslist.list[indx].ctl_type; + return (3); +} + struct ctlname inetname[] = CTL_IPPROTO_NAMES; struct ctlname ipname[] = IPCTL_NAMES; struct ctlname icmpname[] = ICMPCTL_NAMES; diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index a502574dbe1..ce090a7baf3 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.10 1996/06/29 21:07:52 tholo Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.11 1996/08/08 06:36:45 tholo Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -121,11 +121,9 @@ sys___sysctl(p, v, retval) case CTL_NET: fn = net_sysctl; break; -#ifdef notyet case CTL_FS: fn = fs_sysctl; break; -#endif case CTL_MACHDEP: fn = cpu_sysctl; break; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 4cbf0a43afa..888163257e4 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -77,6 +77,7 @@ int vttoif_tab[9] = { int doforce = 1; /* 1 => permit forcible unmounting */ int prtactive = 0; /* 1 => print out reclaim of active vnodes */ +int suid_clear = 1; /* 1 => clear SUID / SGID on owner change */ /* * Insq/Remq for the vnode usage lists. @@ -1610,3 +1611,56 @@ vfs_shutdown() else printf("done\n"); } + +/* + * posix file system related system variables. + */ +int +fs_posix_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + /* all sysctl names at this level are terminal */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case FS_POSIX_SETUID: + if (newp && securelevel > 0) + return (EPERM); + return(sysctl_int(oldp, oldlenp, newp, newlen, &suid_clear)); + default: + return (EOPNOTSUPP); + } + /* NOTREACHED */ +} + +/* + * file system related system variables. + */ +int +fs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + sysctlfn *fn; + + switch (name[0]) { + case FS_POSIX: + fn = fs_posix_sysctl; + break; + default: + return (EOPNOTSUPP); + } + return (*fn)(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p); +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 783d9779c59..36e7dddcd48 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.11 1996/08/08 04:23:03 tholo Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.12 1996/08/08 06:36:47 tholo Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -60,6 +60,8 @@ #include <vm/vm.h> #include <sys/sysctl.h> +extern int suid_clear; + static int change_dir __P((struct nameidata *, struct proc *)); void checkdirs __P((struct vnode *)); @@ -1498,15 +1500,16 @@ sys_chown(p, v, retval) if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { - error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); - if (error) - goto out; - mode = vattr.va_mode; - if (vattr.va_uid != SCARG(uap, uid)) - mode &= ~VSUID; - if (vattr.va_gid != SCARG(uap, gid)) - mode &= ~VSGID; - if (mode == vattr.va_mode) + if (suser(p->p_ucred, &p->p_acflag) || + suid_clear) { + error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); + if (error) + goto out; + mode = vattr.va_mode & ~(VSUID | VSGID); + if (mode == vattr.va_mode) + mode = VNOVAL; + } + else mode = VNOVAL; VATTR_NULL(&vattr); vattr.va_uid = SCARG(uap, uid); @@ -1548,15 +1551,16 @@ sys_fchown(p, v, retval) if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { - error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); - if (error) - goto out; - mode = vattr.va_mode; - if (vattr.va_uid != SCARG(uap, uid)) - mode &= ~VSUID; - if (vattr.va_gid != SCARG(uap, gid)) - mode &= ~VSGID; - if (mode == vattr.va_mode) + if (suser(p->p_ucred, &p->p_acflag) || + suid_clear) { + error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); + if (error) + goto out; + mode = vattr.va_mode & ~(VSUID | VSGID); + if (mode == vattr.va_mode) + mode = VNOVAL; + } + else mode = VNOVAL; VATTR_NULL(&vattr); vattr.va_uid = SCARG(uap, uid); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index eac34cd5995..38a51a50a89 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.7 1996/06/29 21:06:43 tholo Exp $ */ +/* $OpenBSD: sysctl.h,v 1.8 1996/08/08 06:36:48 tholo Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -214,6 +214,28 @@ struct kinfo_proc { }; /* + * CTL_FS identifiers + */ +#define FS_POSIX 1 /* POSIX flags */ +#define FS_MAXID 2 + +#define CTL_FS_NAMES { \ + { 0, 0 }, \ + { "posix", CTLTYPE_NODE }, \ +} + +/* + * CTL_FS identifiers + */ +#define FS_POSIX_SETUID 1 /* int: always clear SGID/SUID bit when owner change */ +#define FS_POSIX_MAXID 2 + +#define CTL_FS_POSIX_NAMES { \ + { 0, 0 }, \ + { "setuid", CTLTYPE_INT }, \ +} + +/* * CTL_HW identifiers */ #define HW_MACHINE 1 /* string: machine class */ diff --git a/usr.sbin/sysctl/sysctl.c b/usr.sbin/sysctl/sysctl.c index a5de0bd9ef8..c05b94f00bf 100644 --- a/usr.sbin/sysctl/sysctl.c +++ b/usr.sbin/sysctl/sysctl.c @@ -76,6 +76,7 @@ static char *rcsid = "$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $" struct ctlname topname[] = CTL_NAMES; struct ctlname kernname[] = CTL_KERN_NAMES; struct ctlname vmname[] = CTL_VM_NAMES; +struct ctlname fsname[] = CTL_FS_NAMES; struct ctlname netname[] = CTL_NET_NAMES; struct ctlname hwname[] = CTL_HW_NAMES; struct ctlname username[] = CTL_USER_NAMES; @@ -95,7 +96,7 @@ struct list secondlevel[] = { { 0, 0 }, /* CTL_UNSPEC */ { kernname, KERN_MAXID }, /* CTL_KERN */ { vmname, VM_MAXID }, /* CTL_VM */ - { 0, 0 }, /* CTL_FS */ + { fsname, FS_MAXID }, /* CTL_FS */ { netname, NET_MAXID }, /* CTL_NET */ { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ { hwname, HW_MAXID }, /* CTL_HW */ @@ -274,6 +275,12 @@ parse(string, flags) fprintf(stderr, "Use ps to view %s information\n", string); return; + case KERN_NTPTIME: + if (flags == 0) + return; + fprintf(stderr, + "Use xntpd to view %s information\n", string); + return; case KERN_CLOCKRATE: special |= CLOCK; break; @@ -328,6 +335,11 @@ parse(string, flags) break; case CTL_FS: + len = sysctl_fs(string, &bufp, mib, flags, &type); + if (len >= 0) + break; + return; + case CTL_USER: case CTL_DDB: break; @@ -484,6 +496,33 @@ debuginit() } } +struct ctlname posixname[] = CTL_FS_POSIX_NAMES; +struct list fslist = { posixname, FS_POSIX_MAXID }; + +/* + * handle file system requests + */ +sysctl_fs(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + if (*bufpp == NULL) { + listall(string, &fslist); + return (-1); + } + if ((indx = findname(string, "third", bufpp, &fslist)) == -1) + return (-1); + mib[2] = indx; + *typep = fslist.list[indx].ctl_type; + return (3); +} + struct ctlname inetname[] = CTL_IPPROTO_NAMES; struct ctlname ipname[] = IPCTL_NAMES; struct ctlname icmpname[] = ICMPCTL_NAMES; |