svn commit: r287209 - in head: share/man/man4 sys/compat/cloudabi sys/kern sys/sys usr.bin/procstat

Ed Schouten ed at FreeBSD.org
Thu Aug 27 15:16:43 UTC 2015


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" },
 


More information about the svn-src-all mailing list