Author: ed
Date: Thu Aug 27 15:16:41 2015
New Revision: 287209
URL: https://svnweb.freebsd.org/changeset/base/287209

Log:
  Decompose linkat()/renameat() rights to source and target.
  
  To make it easier to understand how Capsicum interacts with linkat() and
  renameat(), rename the rights to CAP_{LINK,RENAME}AT_{SOURCE,TARGET}.
  
  This also addresses a shortcoming in Capsicum, where it isn't possible
  to disable linking to files stored in a directory. Creating hardlinks
  essentially makes it possible to access files with additional rights.
  
  Reviewed by:  rwatson, wblock
  Differential Revision:        https://reviews.freebsd.org/D3411

Modified:
  head/share/man/man4/rights.4
  head/sys/compat/cloudabi/cloudabi_fd.c
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/capsicum.h
  head/usr.bin/procstat/procstat_files.c

Modified: head/share/man/man4/rights.4
==============================================================================
--- head/share/man/man4/rights.4        Thu Aug 27 15:03:34 2015        
(r287208)
+++ head/share/man/man4/rights.4        Thu Aug 27 15:16:41 2015        
(r287209)
@@ -32,7 +32,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 23, 2015
+.Dd August 27, 2015
 .Dt RIGHTS 4
 .Os
 .Sh NAME
@@ -71,7 +71,7 @@ The
 family of functions should be used to manage the structure.
 .Sh RIGHTS
 The following rights may be specified in a rights mask:
-.Bl -tag -width CAP_EXTATTR_DELETE
+.Bl -tag -width CAP_RENAMEAT_SOURCE
 .It Dv CAP_ACCEPT
 Permit
 .Xr accept 2
@@ -328,12 +328,28 @@ argument is non-NULL).
 .Dv CAP_EVENT
 is also required on file descriptors that will be monitored using
 .Xr kevent 2 .
-.It Dv CAP_LINKAT
+.It Dv CAP_LINKAT_SOURCE
 Permit
 .Xr linkat 2
-and
-.Xr renameat 2
-on the destination directory descriptor.
+on the source directory descriptor.
+This right includes the
+.Dv CAP_LOOKUP
+right.
+.Pp
+Warning:
+.Dv CAP_LINKAT_SOURCE
+makes it possible to link files in a directory for which file
+descriptors exist that have additional rights.
+For example,
+a file stored in a directory that does not allow
+.Dv CAP_READ
+may be linked in another directory that does allow
+.Dv CAP_READ ,
+thereby granting read access to a file that is otherwise unreadable.
+.It Dv CAP_LINKAT_TARGET
+Permit
+.Xr linkat 2
+on the target directory descriptor.
 This right includes the
 .Dv CAP_LOOKUP
 right.
@@ -474,10 +490,28 @@ is also required) and related system cal
 .It Dv CAP_RECV
 An alias to
 .Dv CAP_READ .
-.It Dv CAP_RENAMEAT
+.It Dv CAP_RENAMEAT_SOURCE
 Permit
-.Xr renameat 2 .
-This right is required on the source directory descriptor.
+.Xr renameat 2
+on the source directory descriptor.
+This right includes the
+.Dv CAP_LOOKUP
+right.
+.Pp
+Warning:
+.Dv CAP_RENAMEAT_SOURCE
+makes it possible to move files to a directory for which file
+descriptors exist that have additional rights.
+For example,
+a file stored in a directory that does not allow
+.Dv CAP_READ
+may be moved to another directory that does allow
+.Dv CAP_READ ,
+thereby granting read access to a file that is otherwise unreadable.
+.It Dv CAP_RENAMEAT_TARGET
+Permit
+.Xr renameat 2
+on the target directory descriptor.
 This right includes the
 .Dv CAP_LOOKUP
 right.

Modified: head/sys/compat/cloudabi/cloudabi_fd.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_fd.c      Thu Aug 27 15:03:34 2015        
(r287208)
+++ head/sys/compat/cloudabi/cloudabi_fd.c      Thu Aug 27 15:16:41 2015        
(r287209)
@@ -56,13 +56,13 @@ __FBSDID("$FreeBSD$");
        MAPPING(CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY, CAP_MKDIRAT)      \
        MAPPING(CLOUDABI_RIGHT_FILE_CREATE_FILE, CAP_CREATE)            \
        MAPPING(CLOUDABI_RIGHT_FILE_CREATE_FIFO, CAP_MKFIFOAT)          \
-       MAPPING(CLOUDABI_RIGHT_FILE_LINK_SOURCE, CAP_LOOKUP)            \
-       MAPPING(CLOUDABI_RIGHT_FILE_LINK_TARGET, CAP_LINKAT)            \
+       MAPPING(CLOUDABI_RIGHT_FILE_LINK_SOURCE, CAP_LINKAT_SOURCE)     \
+       MAPPING(CLOUDABI_RIGHT_FILE_LINK_TARGET, CAP_LINKAT_TARGET)     \
        MAPPING(CLOUDABI_RIGHT_FILE_OPEN, CAP_LOOKUP)                   \
        MAPPING(CLOUDABI_RIGHT_FILE_READDIR, CAP_READ)                  \
        MAPPING(CLOUDABI_RIGHT_FILE_READLINK, CAP_LOOKUP)               \
-       MAPPING(CLOUDABI_RIGHT_FILE_RENAME_SOURCE, CAP_RENAMEAT)        \
-       MAPPING(CLOUDABI_RIGHT_FILE_RENAME_TARGET, CAP_LINKAT)          \
+       MAPPING(CLOUDABI_RIGHT_FILE_RENAME_SOURCE, CAP_RENAMEAT_SOURCE) \
+       MAPPING(CLOUDABI_RIGHT_FILE_RENAME_TARGET, CAP_RENAMEAT_TARGET) \
        MAPPING(CLOUDABI_RIGHT_FILE_STAT_FGET, CAP_FSTAT)               \
        MAPPING(CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE, CAP_FTRUNCATE)      \
        MAPPING(CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES, CAP_FUTIMES)       \

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c        Thu Aug 27 15:03:34 2015        
(r287208)
+++ head/sys/kern/vfs_syscalls.c        Thu Aug 27 15:16:41 2015        
(r287209)
@@ -1441,7 +1441,8 @@ kern_linkat(struct thread *td, int fd1, 
 
 again:
        bwillwrite();
-       NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1, td);
+       NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1,
+           cap_rights_init(&rights, CAP_LINKAT_SOURCE), td);
 
        if ((error = namei(&nd)) != 0)
                return (error);
@@ -1451,9 +1452,9 @@ again:
                vrele(vp);
                return (EPERM);         /* POSIX */
        }
-       NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2 |
-           NOCACHE, segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT),
-           td);
+       NDINIT_ATRIGHTS(&nd, CREATE,
+           LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflg, path2, fd2,
+           cap_rights_init(&rights, CAP_LINKAT_TARGET), td);
        if ((error = namei(&nd)) == 0) {
                if (nd.ni_vp != NULL) {
                        NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -3461,10 +3462,11 @@ again:
 #ifdef MAC
        NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
            AUDITVNODE1, pathseg, old, oldfd,
-           cap_rights_init(&rights, CAP_RENAMEAT), td);
+           cap_rights_init(&rights, CAP_RENAMEAT_SOURCE), td);
 #else
        NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
-           pathseg, old, oldfd, cap_rights_init(&rights, CAP_RENAMEAT), td);
+           pathseg, old, oldfd,
+           cap_rights_init(&rights, CAP_RENAMEAT_SOURCE), td);
 #endif
 
        if ((error = namei(&fromnd)) != 0)
@@ -3479,7 +3481,7 @@ again:
        fvp = fromnd.ni_vp;
        NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
            SAVESTART | AUDITVNODE2, pathseg, new, newfd,
-           cap_rights_init(&rights, CAP_LINKAT), td);
+           cap_rights_init(&rights, CAP_RENAMEAT_TARGET), td);
        if (fromnd.ni_vp->v_type == VDIR)
                tond.ni_cnd.cn_flags |= WILLBEDIR;
        if ((error = namei(&tond)) != 0) {

Modified: head/sys/sys/capsicum.h
==============================================================================
--- head/sys/sys/capsicum.h     Thu Aug 27 15:03:34 2015        (r287208)
+++ head/sys/sys/capsicum.h     Thu Aug 27 15:16:41 2015        (r287209)
@@ -150,16 +150,16 @@
 #define        CAP_FUTIMES             CAPRIGHT(0, 0x0000000000200000ULL)
 /* Allows for futimens(2), futimes(2), futimesat(2) and utimensat(2). */
 #define        CAP_FUTIMESAT           (CAP_FUTIMES | CAP_LOOKUP)
-/* Allows for linkat(2) and renameat(2) (destination directory descriptor). */
-#define        CAP_LINKAT              (CAP_LOOKUP | 0x0000000000400000ULL)
+/* Allows for linkat(2) (target directory descriptor). */
+#define        CAP_LINKAT_TARGET       (CAP_LOOKUP | 0x0000000000400000ULL)
 /* Allows for mkdirat(2). */
 #define        CAP_MKDIRAT             (CAP_LOOKUP | 0x0000000000800000ULL)
 /* Allows for mkfifoat(2). */
 #define        CAP_MKFIFOAT            (CAP_LOOKUP | 0x0000000001000000ULL)
 /* Allows for mknodat(2). */
 #define        CAP_MKNODAT             (CAP_LOOKUP | 0x0000000002000000ULL)
-/* Allows for renameat(2). */
-#define        CAP_RENAMEAT            (CAP_LOOKUP | 0x0000000004000000ULL)
+/* Allows for renameat(2) (source directory descriptor). */
+#define        CAP_RENAMEAT_SOURCE     (CAP_LOOKUP | 0x0000000004000000ULL)
 /* Allows for symlinkat(2). */
 #define        CAP_SYMLINKAT           (CAP_LOOKUP | 0x0000000008000000ULL)
 /*
@@ -197,6 +197,11 @@
 /* Allows for connectat(2) on a directory descriptor. */
 #define        CAP_CONNECTAT           (CAP_LOOKUP | 0x0000010000000000ULL)
 
+/* Allows for linkat(2) (source directory descriptor). */
+#define        CAP_LINKAT_SOURCE       (CAP_LOOKUP | 0x0000020000000000ULL)
+/* Allows for renameat(2) (target directory descriptor). */
+#define        CAP_RENAMEAT_TARGET     (CAP_LOOKUP | 0x0000040000000000ULL)
+
 #define        CAP_SOCK_CLIENT \
        (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
         CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
@@ -206,10 +211,10 @@
         CAP_SETSOCKOPT | CAP_SHUTDOWN)
 
 /* All used bits for index 0. */
-#define        CAP_ALL0                CAPRIGHT(0, 0x000001FFFFFFFFFFULL)
+#define        CAP_ALL0                CAPRIGHT(0, 0x000007FFFFFFFFFFULL)
 
 /* Available bits for index 0. */
-#define        CAP_UNUSED0_42          CAPRIGHT(0, 0x0000020000000000ULL)
+#define        CAP_UNUSED0_44          CAPRIGHT(0, 0x0000080000000000ULL)
 /* ... */
 #define        CAP_UNUSED0_57          CAPRIGHT(0, 0x0100000000000000ULL)
 

Modified: head/usr.bin/procstat/procstat_files.c
==============================================================================
--- head/usr.bin/procstat/procstat_files.c      Thu Aug 27 15:03:34 2015        
(r287208)
+++ head/usr.bin/procstat/procstat_files.c      Thu Aug 27 15:16:41 2015        
(r287209)
@@ -158,11 +158,13 @@ static struct cap_desc {
        { CAP_FSTAT,            "fs" },
        { CAP_FSTATFS,          "sf" },
        { CAP_FUTIMES,          "fu" },
-       { CAP_LINKAT,           "li" },
+       { CAP_LINKAT_SOURCE,    "ls" },
+       { CAP_LINKAT_TARGET,    "lt" },
        { CAP_MKDIRAT,          "md" },
        { CAP_MKFIFOAT,         "mf" },
        { CAP_MKNODAT,          "mn" },
-       { CAP_RENAMEAT,         "rn" },
+       { CAP_RENAMEAT_SOURCE,  "rs" },
+       { CAP_RENAMEAT_TARGET,  "rt" },
        { CAP_SYMLINKAT,        "sl" },
        { CAP_UNLINKAT,         "un" },
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to