Hi,

I ported the two FreeBSD sysctl's

- security.bsd.hardlink_check_uid
- security.bsd.hardlink_check_gid

to DragonFly. If this sysctls are active unprivileged users cannot create hard links to files owned by other users/groups. I added the sysctl's under kern, not security.bsd ...

Greets

        Matthias

diff -urN sys.orig/kern/vfs_syscalls.c sys/kern/vfs_syscalls.c
--- sys.orig/kern/vfs_syscalls.c        2005-09-17 09:43:00.000000000 +0200
+++ sys/kern/vfs_syscalls.c     2005-09-26 10:39:39.000000000 +0200
@@ -1569,6 +1569,46 @@
        return (error);
 }
 
+static int hardlink_check_uid = 0;
+SYSCTL_INT(_kern, 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(_kern, 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)
+               return (0);
+       
+       error = VOP_GETATTR(vp, &va, 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 nlookupdata *nd, struct nlookupdata *linknd)
 {
@@ -1613,7 +1653,9 @@
        /*
         * Finally run the new API VOP.
         */
-       error = VOP_NLINK(linknd->nl_ncp, vp, linknd->nl_cred);
+       error = can_hardlink(vp, td, td->td_proc->p_ucred);
+       if (error == 0)
+               error = VOP_NLINK(linknd->nl_ncp, vp, linknd->nl_cred);
        vput(vp);
        return (error);
 }

Reply via email to