summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-03-08 20:37:25 +0000
committerpjd <pjd@FreeBSD.org>2004-03-08 20:37:25 +0000
commitb2d1dcd93670e3f0966ed44e57e8bab20417a47f (patch)
tree64ca763f99f243fbacce9577254859350630de99 /sys/kern
parent7d850e036915647286ba968117268c61c4896e3e (diff)
downloadFreeBSD-src-b2d1dcd93670e3f0966ed44e57e8bab20417a47f.zip
FreeBSD-src-b2d1dcd93670e3f0966ed44e57e8bab20417a47f.tar.gz
Add two new sysctls:
- security.bsd.hardlink_check_uid, when set, means, that unprivileged users are not permitted to create hard links to files not owned by them, - security.bsd.hardlink_check_gid, when set, means, that unprivileged users are not permitted to create hard links to files owned by group they don't belong to. OK'ed by: rwatson
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_extattr.c48
-rw-r--r--sys/kern/vfs_syscalls.c48
2 files changed, 92 insertions, 4 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 79a0ce9..d06ba27 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -1358,6 +1358,48 @@ link(td, uap)
return (kern_link(td, uap->path, uap->link, UIO_USERSPACE));
}
+SYSCTL_DECL(_security_bsd);
+
+static int hardlink_check_uid = 0;
+SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
+ &hardlink_check_uid, 0,
+ "Unprivileged processes cannot create hard links to files owned by other "
+ "users");
+static int hardlink_check_gid = 0;
+SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
+ &hardlink_check_gid, 0,
+ "Unprivileged processes cannot create hard links to files owned by other "
+ "groups");
+
+static int
+can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
+{
+ struct vattr va;
+ int error;
+
+ if (suser_cred(cred, PRISON_ROOT) == 0)
+ return (0);
+
+ if (!hardlink_check_uid && !hardlink_check_gid)
+ return (0);
+
+ error = VOP_GETATTR(vp, &va, cred, td);
+ if (error != 0)
+ return (error);
+
+ if (hardlink_check_uid) {
+ if (cred->cr_uid != va.va_uid)
+ return (EPERM);
+ }
+
+ if (hardlink_check_gid) {
+ if (!groupmember(va.va_gid, cred))
+ return (EPERM);
+ }
+
+ return (0);
+}
+
int
kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
{
@@ -1393,9 +1435,11 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
== 0) {
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
+ error = can_hardlink(vp, td, td->td_ucred);
+ if (error == 0)
#ifdef MAC
- error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp,
- vp, &nd.ni_cnd);
+ error = mac_check_vnode_link(td->td_ucred,
+ nd.ni_dvp, vp, &nd.ni_cnd);
if (error == 0)
#endif
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 79a0ce9..d06ba27 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1358,6 +1358,48 @@ link(td, uap)
return (kern_link(td, uap->path, uap->link, UIO_USERSPACE));
}
+SYSCTL_DECL(_security_bsd);
+
+static int hardlink_check_uid = 0;
+SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
+ &hardlink_check_uid, 0,
+ "Unprivileged processes cannot create hard links to files owned by other "
+ "users");
+static int hardlink_check_gid = 0;
+SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
+ &hardlink_check_gid, 0,
+ "Unprivileged processes cannot create hard links to files owned by other "
+ "groups");
+
+static int
+can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
+{
+ struct vattr va;
+ int error;
+
+ if (suser_cred(cred, PRISON_ROOT) == 0)
+ return (0);
+
+ if (!hardlink_check_uid && !hardlink_check_gid)
+ return (0);
+
+ error = VOP_GETATTR(vp, &va, cred, td);
+ if (error != 0)
+ return (error);
+
+ if (hardlink_check_uid) {
+ if (cred->cr_uid != va.va_uid)
+ return (EPERM);
+ }
+
+ if (hardlink_check_gid) {
+ if (!groupmember(va.va_gid, cred))
+ return (EPERM);
+ }
+
+ return (0);
+}
+
int
kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
{
@@ -1393,9 +1435,11 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
== 0) {
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
+ error = can_hardlink(vp, td, td->td_ucred);
+ if (error == 0)
#ifdef MAC
- error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp,
- vp, &nd.ni_cnd);
+ error = mac_check_vnode_link(td->td_ucred,
+ nd.ni_dvp, vp, &nd.ni_cnd);
if (error == 0)
#endif
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
OpenPOWER on IntegriCloud