svn commit: r343891 - in head/sys: kern sys
Konstantin Belousov
kib at FreeBSD.org
Fri Feb 8 04:18:19 UTC 2019
Author: kib
Date: Fri Feb 8 04:18:17 2019
New Revision: 343891
URL: https://svnweb.freebsd.org/changeset/base/343891
Log:
Fix renameat(2) for CAPABILITIES kernels.
When renameat(2) is used with:
- absolute path for to;
- tofd not set to AT_FDCWD;
- the target exists
kern_renameat() requires CAP_UNLINK capability on tofd, but
corresponding namei ni_filecap is not initialized at all because the
lookup is absolute. As result, the check was done against empty filecap
and syscall fails erronously.
Fix it by creating a return flags namei member and reporting if the
lookup was absolute, then do not touch to.ni_filecaps at all.
PR: 222258
Reviewed by: jilles, ngie
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
X-MFC-note: KBI breakage
Differential revision: https://reviews.freebsd.org/D19096
Modified:
head/sys/kern/vfs_lookup.c
head/sys/kern/vfs_syscalls.c
head/sys/sys/namei.h
Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c Fri Feb 8 04:06:48 2019 (r343890)
+++ head/sys/kern/vfs_lookup.c Fri Feb 8 04:18:17 2019 (r343891)
@@ -410,6 +410,7 @@ namei(struct nameidata *ndp)
dp = NULL;
cnp->cn_nameptr = cnp->cn_pnbuf;
if (cnp->cn_pnbuf[0] == '/') {
+ ndp->ni_resflags |= NIRES_ABS;
error = namei_handle_root(ndp, &dp);
} else {
if (ndp->ni_startdir != NULL) {
@@ -1302,6 +1303,7 @@ NDINIT_ALL(struct nameidata *ndp, u_long op, u_long fl
ndp->ni_dirp = namep;
ndp->ni_dirfd = dirfd;
ndp->ni_startdir = startdir;
+ ndp->ni_resflags = 0;
filecaps_init(&ndp->ni_filecaps);
ndp->ni_cnd.cn_thread = td;
if (rightsp != NULL)
Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c Fri Feb 8 04:06:48 2019 (r343890)
+++ head/sys/kern/vfs_syscalls.c Fri Feb 8 04:18:17 2019 (r343891)
@@ -3544,10 +3544,10 @@ again:
goto out;
}
#ifdef CAPABILITIES
- if (newfd != AT_FDCWD) {
+ if (newfd != AT_FDCWD && (tond.ni_resflags & NIRES_ABS) == 0) {
/*
* If the target already exists we require CAP_UNLINKAT
- * from 'newfd'.
+ * from 'newfd', when newfd was used for the lookup.
*/
error = cap_check(&tond.ni_filecaps.fc_rights,
&cap_unlinkat_rights);
Modified: head/sys/sys/namei.h
==============================================================================
--- head/sys/sys/namei.h Fri Feb 8 04:06:48 2019 (r343890)
+++ head/sys/sys/namei.h Fri Feb 8 04:18:17 2019 (r343891)
@@ -88,6 +88,10 @@ struct nameidata {
struct vnode *ni_vp; /* vnode of result */
struct vnode *ni_dvp; /* vnode of intermediate directory */
/*
+ * Results: flags returned from namei
+ */
+ u_int ni_resflags;
+ /*
* Shared between namei and lookup/commit routines.
*/
size_t ni_pathlen; /* remaining chars in path */
@@ -158,6 +162,11 @@ struct nameidata {
#define TRAILINGSLASH 0x10000000 /* path ended in a slash */
#define NOCAPCHECK 0x20000000 /* do not perform capability checks */
#define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */
+
+/*
+ * Namei results flags
+ */
+#define NIRES_ABS 0x00000001 /* Path was absolute */
/*
* Flags in ni_lcf, valid for the duration of the namei call.
More information about the svn-src-head
mailing list