summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortholo <tholo@openbsd.org>1996-08-08 06:36:45 +0000
committertholo <tholo@openbsd.org>1996-08-08 06:36:45 +0000
commit86d967db7ecd9da5e9e0d430000bcad2c0290a59 (patch)
tree0a91e01bdaf65f62d66e604f31a045480762b916
parentDisable RFC 1323 extensions by default (diff)
downloadwireguard-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.c41
-rw-r--r--sys/kern/kern_sysctl.c4
-rw-r--r--sys/kern/vfs_subr.c54
-rw-r--r--sys/kern/vfs_syscalls.c42
-rw-r--r--sys/sys/sysctl.h24
-rw-r--r--usr.sbin/sysctl/sysctl.c41
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;