Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F96230040
D29111.id85294.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D29111.id85294.diff
View Options
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -319,6 +319,7 @@
ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
ndp->ni_resflags |= NIRES_STRICTREL;
if (ndp->ni_dirfd == AT_FDCWD) {
+ /* XXXKIB allow for EMPTYPATH ? */
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
@@ -466,7 +467,6 @@
* Don't allow empty pathnames.
*/
if (__predict_false(*cnp->cn_pnbuf == '\0')) {
- namei_cleanup_cnp(cnp);
return (ENOENT);
}
@@ -554,6 +554,28 @@
error = namei_getpath(ndp);
if (__predict_false(error != 0)) {
+ if (error == ENOENT) {
+ MPASS(*cnp->cn_pnbuf == '\0');
+ if ((cnp->cn_flags & EMPTYPATH) != 0) {
+ MPASS((cnp->cn_flags & (LOCKLEAF |
+ LOCKPARENT | LOCKSHARED |
+ WANTPARENT)) == 0);
+ error = namei_setup(ndp, &dp, &pwd);
+ if (error == 0) {
+ ndp->ni_vp = dp;
+ vref(dp);
+ SDT_PROBE4(vfs, namei, lookup, return,
+ error, ndp->ni_vp, false, ndp);
+ namei_cleanup_cnp(cnp);
+ pwd_drop(pwd);
+ ndp->ni_resflags |= NIRES_EMPTYPATH;
+ NDVALIDATE(ndp);
+ return (0);
+ }
+ }
+ namei_cleanup_cnp(cnp);
+ }
+ SDT_PROBE4(vfs, namei, lookup, return, error, NULL, false, ndp);
return (error);
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -129,6 +129,8 @@
res |= (at_flags & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW :
FOLLOW;
}
+ if ((mask & AT_EMPTY_PATH) != 0 && (at_flags & AT_EMPTY_PATH) != 0)
+ res |= EMPTYPATH;
return (res);
}
@@ -1496,12 +1498,13 @@
int flag;
flag = uap->flag;
- if ((flag & ~(AT_SYMLINK_FOLLOW | AT_RESOLVE_BENEATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_FOLLOW | AT_RESOLVE_BENEATH |
+ AT_EMPTY_PATH)) != 0)
return (EINVAL);
return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2,
UIO_USERSPACE, at2cnpflags(flag, AT_SYMLINK_FOLLOW |
- AT_RESOLVE_BENEATH)));
+ AT_RESOLVE_BENEATH | AT_EMPTY_PATH)));
}
int hardlink_check_uid = 0;
@@ -1578,6 +1581,23 @@
LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd,
&cap_linkat_target_rights, td);
if ((error = namei(&nd)) == 0) {
+ if ((nd.ni_resflags & NIRES_EMPTYPATH) != 0) {
+ error = priv_check(td, PRIV_VFS_FHOPEN);
+ if (error != 0) {
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (nd.ni_vp != NULL) {
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ vrele(nd.ni_vp);
+ } else {
+ vput(nd.ni_dvp);
+ }
+ vrele(vp);
+ return (error);
+ }
+ }
if (nd.ni_vp != NULL) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp == nd.ni_vp)
@@ -2710,7 +2730,8 @@
sys_chflagsat(struct thread *td, struct chflagsat_args *uap)
{
- if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0)
+ if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH |
+ AT_EMPTY_PATH)) != 0)
return (EINVAL);
return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE,
@@ -2743,8 +2764,8 @@
AUDIT_ARG_FFLAGS(flags);
NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(atflag, AT_SYMLINK_NOFOLLOW |
- AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
- &cap_fchflags_rights, td);
+ AT_RESOLVE_BENEATH | AT_EMPTY_PATH) | AUDITVNODE1, pathseg, path,
+ fd, &cap_fchflags_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE_NOTHING(&nd);
@@ -2838,7 +2859,8 @@
sys_fchmodat(struct thread *td, struct fchmodat_args *uap)
{
- if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0)
+ if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH |
+ AT_EMPTY_PATH)) != 0)
return (EINVAL);
return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE,
@@ -2871,8 +2893,8 @@
AUDIT_ARG_MODE(mode);
NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
- AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
- &cap_fchmod_rights, td);
+ AT_RESOLVE_BENEATH | AT_EMPTY_PATH) | AUDITVNODE1, pathseg, path,
+ fd, &cap_fchmod_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE_NOTHING(&nd);
@@ -2966,7 +2988,8 @@
sys_fchownat(struct thread *td, struct fchownat_args *uap)
{
- if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0)
+ if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH |
+ AT_EMPTY_PATH)) != 0)
return (EINVAL);
return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid,
@@ -2982,8 +3005,8 @@
AUDIT_ARG_OWNER(uid, gid);
NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
- AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd,
- &cap_fchown_rights, td);
+ AT_RESOLVE_BENEATH | AT_EMPTY_PATH) | AUDITVNODE1, pathseg, path,
+ fd, &cap_fchown_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3334,13 +3357,14 @@
struct timespec ts[2];
int error, flags;
- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH |
+ AT_EMPTY_PATH)) != 0)
return (EINVAL);
if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0)
return (error);
NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW |
- AT_RESOLVE_BENEATH) | AUDITVNODE1,
+ AT_RESOLVE_BENEATH | AT_EMPTY_PATH) | AUDITVNODE1,
pathseg, path, fd, &cap_futimes_rights, td);
if ((error = namei(&nd)) != 0)
return (error);
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -222,6 +222,7 @@
/* #define AT_UNUSED1 0x1000 *//* Was AT_BENEATH */
#define AT_RESOLVE_BENEATH 0x2000 /* Do not allow name resolution
to walk out of dirfd */
+#define AT_EMPTY_PATH 0x4000
#endif
/*
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -144,10 +144,12 @@
#define WANTPARENT 0x0010 /* want parent vnode returned unlocked */
#define FAILIFEXISTS 0x0020 /* return EEXIST if found */
#define FOLLOW 0x0040 /* follow symbolic links */
+#define EMPTYPATH 0x0080 /* Allow empty path for *at */
#define LOCKSHARED 0x0100 /* Shared lock leaf */
#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */
#define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */
#define MODMASK 0xf000001ffULL /* mask of operational modifiers */
+
/*
* Namei parameter descriptors.
*
@@ -198,6 +200,7 @@
*/
#define NIRES_ABS 0x00000001 /* Path was absolute */
#define NIRES_STRICTREL 0x00000002 /* Restricted lookup result */
+#define NIRES_EMPTYPATH 0x00000004
/*
* Flags in ni_lcf, valid for the duration of the namei call.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Sep 25, 3:58 AM (18 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12727785
Default Alt Text
D29111.id85294.diff (6 KB)
Attached To
Mode
D29111: Add AT_EMPTY_PATH
Attached
Detach File
Event Timeline
Log In to Comment