Page MenuHomeFreeBSD

D14567.id44045.diff
No OneTemporary

D14567.id44045.diff

Index: include/unistd.h
===================================================================
--- include/unistd.h
+++ include/unistd.h
@@ -583,6 +583,7 @@
int undelete(const char *);
int unwhiteout(const char *);
void *valloc(size_t); /* obsoleted by malloc() */
+int fdunlinkat(int, const char *, int, int);
#ifndef _OPTRESET_DECLARED
#define _OPTRESET_DECLARED
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -478,6 +478,7 @@
MLINKS+=thr_kill.2 thr_kill2.2
MLINKS+=truncate.2 ftruncate.2
MLINKS+=unlink.2 unlinkat.2
+MLINKS+=unlink.2 fdunlinkat.2
MLINKS+=utimensat.2 futimens.2
MLINKS+=utimes.2 futimes.2 \
utimes.2 futimesat.2 \
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -400,6 +400,7 @@
statfs;
cpuset_getdomain;
cpuset_setdomain;
+ fdunlinkat;
};
FBSDprivate_1.0 {
Index: lib/libc/sys/unlink.2
===================================================================
--- lib/libc/sys/unlink.2
+++ lib/libc/sys/unlink.2
@@ -28,7 +28,7 @@
.\" @(#)unlink.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd December 1, 2017
+.Dd June 10, 2018
.Dt UNLINK 2
.Os
.Sh NAME
@@ -42,7 +42,9 @@
.Ft int
.Fn unlink "const char *path"
.Ft int
-.Fn unlinkat "int fd" "const char *path" "int flag"
+.Fn unlinkat "int dfd" "const char *path" "int flag"
+.Ft int
+.Fn fdunlinkat "int dfd" "const char *path" "int fd" "int flag"
.Sh DESCRIPTION
The
.Fn unlink
@@ -74,7 +76,7 @@
specifies a relative path.
In this case the directory entry to be removed is determined
relative to the directory associated with the file descriptor
-.Fa fd
+.Fa dfd
instead of the current working directory.
.Pp
The values for
@@ -105,6 +107,26 @@
respectively, depending on whether or not the
.Dv AT_REMOVEDIR
bit is set in flag.
+.Pp
+The
+.Fn fdunlinkat
+system call can be used to unlink an already-opened file, unless that
+file has been replaced since it was opened.
+It is equivalent to
+.Fn unlinkat
+in the case where
+.Fa path
+is already open as the file descriptor
+.Fa fd .
+Otherwise, the path will not be removed and an error will be returned.
+The
+.Fa fd
+can be set the
+.Dv FD_NONE
+in that case
+.Fn fdunlinkat
+behaves exactly like
+.Fn unlinkat .
.Sh RETURN VALUES
.Rv -std unlink
.Sh ERRORS
@@ -201,6 +223,15 @@
.Dv AT_FDCWD
nor a file descriptor associated with a directory.
.El
+.Pp
+In addition to the errors returned by the
+.Fn unlinkat ,
+.Fn fdunlinkat
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The file descriptor is not associated with the path.
+.El
.Sh SEE ALSO
.Xr chflags 2 ,
.Xr close 2 ,
@@ -220,6 +251,10 @@
.Fn unlinkat
system call appeared in
.Fx 8.0 .
+The
+.Fn fdunlinkat
+system call appeared in
+.Fx 12.0 .
.Pp
The
.Fn unlink
Index: sys/amd64/conf/CAPSICUM
===================================================================
--- sys/amd64/conf/CAPSICUM
+++ sys/amd64/conf/CAPSICUM
@@ -1,91 +0,0 @@
-
-
-
-
-cpu HAMMER
-ident CAPSICUM
-
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
-makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support
-
-options SCHED_ULE # ULE scheduler
-options PREEMPTION # Enable kernel thread preemption
-options INET # InterNETworking
-options INET6 # IPv6 communications protocols
-options TCP_OFFLOAD # TCP offload
-options SCTP # Stream Control Transmission Protocol
-options NFSCL # New Network Filesystem client
-options NFS_ROOT # NFS usable as /, requires NFSCL
-options COMPAT_FREEBSD32 # Compatible with i386 binaries
-options COMPAT_FREEBSD4 # Compatible with FreeBSD4
-options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-options COMPAT_FREEBSD7 # Compatible with FreeBSD7
-options KTRACE # ktrace(1) support
-options STACK # stack(9) support
-options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
-options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
-options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
-options AUDIT # Security event auditing
-options CAPABILITY_MODE # Capsicum capability mode
-options CAPABILITIES # Capsicum capabilities
-options MAC # TrustedBSD MAC Framework
-options KDTRACE_FRAME # Ensure frames are compiled in
-options KDTRACE_HOOKS # Kernel DTrace hooks
-options DDB_CTF # Kernel ELF linker loads CTF data
-
-# Debugging support. Always need this:
-options KDB # Enable kernel debugger support.
-# For minimum debugger support (stable branch) use:
-#options KDB_TRACE # Print a stack trace for a panic.
-# For full debugger support use this instead:
-options DDB # Support DDB.
-options INVARIANTS # Enable calls of extra sanity checking
-options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-options WITNESS # Enable checks to detect deadlocks and cycles
-options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
-options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
-
-# Bus support.
-device acpi
-device pci
-
-# atkbdc0 controls both the keyboard and the PS/2 mouse
-device atkbdc # AT keyboard controller
-device atkbd # AT keyboard
-
-device kbdmux # keyboard multiplexer
-
-device vga # VGA video card driver
-options VESA # Add support for VESA BIOS Extensions (VBE)
-
-# syscons is the default console driver, resembling an SCO console
-device sc
-options SC_PIXEL_MODE # add support for the raster text mode
-
-# Serial (COM) ports
-device uart # Generic UART driver
-
-# Pseudo devices.
-device loop # Network loopback
-device random # Entropy device
-device ether # Ethernet support
-
-# The `bpf' device enables the Berkeley Packet Filter.
-# Be aware of the administrative consequences of enabling this!
-# Note that 'bpf' is required for DHCP.
-device bpf # Berkeley packet filter
-
-device le
-
-
-# VirtIO support
-device virtio # Generic VirtIO bus (required)
-device virtio_pci # VirtIO PCI device
-device vtnet # VirtIO Ethernet device
-device virtio_blk # VirtIO Block device
-device virtio_scsi # VirtIO SCSI device
-device virtio_balloon # VirtIO Memory Balloon device
-device virtio_scsi # VirtIO SCSI device
-device virtio_balloon # VirtIO Memory Balloon device
Index: sys/cddl/compat/opensolaris/sys/vnode.h
===================================================================
--- sys/cddl/compat/opensolaris/sys/vnode.h
+++ sys/cddl/compat/opensolaris/sys/vnode.h
@@ -278,7 +278,7 @@
ASSERT(seg == UIO_SYSSPACE);
ASSERT(dirflag == RMFILE);
- return (kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0));
+ return (kern_fdunlinkat(curthread, AT_FDCWD, fnamep, FD_NONE, seg, 0));
}
#endif /* _KERNEL */
Index: sys/compat/cloudabi/cloudabi_file.c
===================================================================
--- sys/compat/cloudabi/cloudabi_file.c
+++ sys/compat/cloudabi/cloudabi_file.c
@@ -750,9 +750,11 @@
return (error);
if (uap->flags & CLOUDABI_UNLINK_REMOVEDIR)
- error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE);
+ error = kern_fdrmdirat(td, uap->fd, path, FD_NONE,
+ UIO_SYSSPACE);
else
- error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0);
+ error = kern_fdunlinkat(td, uap->fd, path, FD_NONE,
+ UIO_SYSSPACE, 0);
cloudabi_freestr(path);
return (error);
}
Index: sys/compat/freebsd32/capabilities.conf
===================================================================
--- sys/compat/freebsd32/capabilities.conf
+++ sys/compat/freebsd32/capabilities.conf
@@ -192,6 +192,7 @@
renameat
symlinkat
unlinkat
+fdunlinkat
freebsd32_utimensat
pdfork
pdgetpid
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1123,5 +1123,7 @@
cpuwhich_t which, uint32_t id1, uint32_t id2, \
size_t domainsetsize, domainset_t *mask, \
int policy); }
+563 AUE_UNLINKAT NOPROTO { int fdunlinkat(int dfd, const char *path, int fd, \
+ int flag, mode_t mode); }
; vim: syntax=off
Index: sys/compat/linux/linux_file.c
===================================================================
--- sys/compat/linux/linux_file.c
+++ sys/compat/linux/linux_file.c
@@ -580,7 +580,7 @@
printf(ARGS(unlink, "%s"), path);
#endif
- error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0);
+ error = kern_fdunlinkat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0);
if (error == EPERM) {
/* Introduce POSIX noncompliant behaviour of Linux */
if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st,
@@ -612,9 +612,9 @@
#endif
if (args->flag & LINUX_AT_REMOVEDIR)
- error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE);
+ error = kern_fdrmdirat(td, dfd, path, FD_NONE, UIO_SYSSPACE);
else
- error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0);
+ error = kern_fdunlinkat(td, dfd, path, FD_NONE, UIO_SYSSPACE, 0);
if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) {
/* Introduce POSIX noncompliant behaviour of Linux */
if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path,
@@ -725,7 +725,7 @@
if (ldebug(rmdir))
printf(ARGS(rmdir, "%s"), path);
#endif
- error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE);
+ error = kern_fdrmdirat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE);
LFREEPATH(path);
return (error);
}
Index: sys/i386/ibcs2/ibcs2_misc.c
===================================================================
--- sys/i386/ibcs2/ibcs2_misc.c
+++ sys/i386/ibcs2/ibcs2_misc.c
@@ -1071,7 +1071,7 @@
int error;
CHECKALTEXIST(td, uap->path, &path);
- error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0);
+ error = kern_fdunlinkat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0);
free(path, M_TEMP);
return (error);
}
@@ -1120,7 +1120,7 @@
int error;
CHECKALTEXIST(td, uap->path, &path);
- error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE);
+ error = kern_fdrmdirat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE);
free(path, M_TEMP);
return (error);
}
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -463,6 +463,7 @@
renameat
symlinkat
unlinkat
+fdunlinkat
utimensat
##
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -1027,6 +1027,8 @@
cpuwhich_t which, id_t id, \
size_t domainsetsize, domainset_t *mask, \
int policy); }
+563 AUE_UNLINKAT STD { int fdunlinkat(int dfd, const char *path, int fd, \
+ int flag, mode_t mode); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/vfs_mountroot.c
===================================================================
--- sys/kern/vfs_mountroot.c
+++ sys/kern/vfs_mountroot.c
@@ -388,7 +388,7 @@
if (mporoot == mpdevfs) {
vfs_unbusy(mpdevfs);
/* Unlink the no longer needed /dev/dev -> / symlink */
- error = kern_unlinkat(td, AT_FDCWD, "/dev/dev",
+ error = kern_fdunlinkat(td, AT_FDCWD, "/dev/dev", FD_NONE,
UIO_SYSSPACE, 0);
if (error)
printf("mountroot: unable to unlink /dev/dev "
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -1737,7 +1737,22 @@
sys_unlink(struct thread *td, struct unlink_args *uap)
{
- return (kern_unlinkat(td, AT_FDCWD, uap->path, UIO_USERSPACE, 0));
+ return (kern_fdunlinkat(td, AT_FDCWD, uap->path, FD_NONE, UIO_USERSPACE,
+ 0));
+}
+
+static int
+kern_fdunlinkat_ex(struct thread *td, int dfd, const char *path, int fd,
+ int flag, enum uio_seg pathseg, ino_t oldinum)
+{
+
+ if ((flag & ~AT_REMOVEDIR) != 0)
+ return (EINVAL);
+
+ if ((flag & AT_REMOVEDIR) != 0)
+ return (kern_fdrmdirat(td, dfd, path, fd, UIO_USERSPACE));
+
+ return (kern_fdunlinkat(td, dfd, path, fd, UIO_USERSPACE, 0));
}
#ifndef _SYS_SYSPROTO_H_
@@ -1750,43 +1765,65 @@
int
sys_unlinkat(struct thread *td, struct unlinkat_args *uap)
{
- int flag = uap->flag;
- int fd = uap->fd;
- char *path = uap->path;
- if (flag & ~AT_REMOVEDIR)
- return (EINVAL);
+ return (kern_fdunlinkat_ex(td, uap->fd, uap->path, FD_NONE, uap->flag,
+ UIO_USERSPACE, 0));
+}
- if (flag & AT_REMOVEDIR)
- return (kern_rmdirat(td, fd, path, UIO_USERSPACE));
- else
- return (kern_unlinkat(td, fd, path, UIO_USERSPACE, 0));
+#ifndef _SYS_SYSPROTO_H_
+struct fdunlinkat_args {
+ int dfd;
+ const char *path;
+ int fd;
+ int flag;
+};
+#endif
+int
+sys_fdunlinkat(struct thread *td, struct fdunlinkat_args *uap)
+{
+
+ return (kern_fdunlinkat_ex(td, uap->dfd, uap->path, uap->fd, uap->flag,
+ UIO_USERSPACE, 0));
}
int
-kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
- ino_t oldinum)
+kern_fdunlinkat(struct thread *td, int dfd, const char *path, int fd,
+ enum uio_seg pathseg, ino_t oldinum)
{
struct mount *mp;
+ struct file *fp;
struct vnode *vp;
struct nameidata nd;
struct stat sb;
cap_rights_t rights;
int error;
+ fp = NULL;
+ if (fd != FD_NONE) {
+ error = getvnode(td, fd, cap_rights_init(&rights, CAP_LOOKUP),
+ &fp);
+ if (error != 0)
+ return (error);
+ }
+
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
- pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td);
- if ((error = namei(&nd)) != 0)
- return (error == EINVAL ? EPERM : error);
+ pathseg, path, dfd, cap_rights_init(&rights, CAP_UNLINKAT), td);
+ if ((error = namei(&nd)) != 0) {
+ if (error == EINVAL)
+ error = EPERM;
+ goto fdout;
+ }
vp = nd.ni_vp;
if (vp->v_type == VDIR && oldinum == 0) {
error = EPERM; /* POSIX */
} else if (oldinum != 0 &&
((error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td)) == 0) &&
sb.st_ino != oldinum) {
- error = EIDRM; /* Identifier removed */
+ error = EIDRM; /* Identifier removed */
+ } else if (fp != NULL && fp->f_vnode != vp) {
+ error = EAGAIN;
} else {
/*
* The root of a mounted filesystem cannot be deleted.
@@ -1805,8 +1842,9 @@
else
vput(vp);
if ((error = vn_start_write(NULL, &mp,
- V_XSLEEP | PCATCH)) != 0)
- return (error);
+ V_XSLEEP | PCATCH)) != 0) {
+ goto fdout;
+ }
goto restart;
}
#ifdef MAC
@@ -1828,6 +1866,9 @@
vrele(vp);
else
vput(vp);
+fdout:
+ if (fp != NULL)
+ fdrop(fp, td);
return (error);
}
@@ -2645,7 +2686,7 @@
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_FFLAGS(uap->flags);
- error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FCHFLAGS),
+ error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_LOOKUP),
&fp);
if (error != 0)
return (error);
@@ -3675,24 +3716,35 @@
sys_rmdir(struct thread *td, struct rmdir_args *uap)
{
- return (kern_rmdirat(td, AT_FDCWD, uap->path, UIO_USERSPACE));
+ return (kern_fdrmdirat(td, AT_FDCWD, uap->path, FD_NONE,
+ UIO_USERSPACE));
}
int
-kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
+kern_fdrmdirat(struct thread *td, int dfd, const char *path, int fd,
+ enum uio_seg pathseg)
{
struct mount *mp;
struct vnode *vp;
+ struct file *fp;
struct nameidata nd;
cap_rights_t rights;
int error;
+ fp = NULL;
+ if (fd != FD_NONE) {
+ error = getvnode(td, fd, cap_rights_init(&rights, CAP_LOOKUP),
+ &fp);
+ if (error != 0)
+ return (error);
+ }
+
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
- pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td);
+ pathseg, path, dfd, cap_rights_init(&rights, CAP_UNLINKAT), td);
if ((error = namei(&nd)) != 0)
- return (error);
+ goto fdout;
vp = nd.ni_vp;
if (vp->v_type != VDIR) {
error = ENOTDIR;
@@ -3712,6 +3764,12 @@
error = EBUSY;
goto out;
}
+
+ if (fp != NULL && fp->f_vnode != vp) {
+ error = EAGAIN;
+ goto out;
+ }
+
#ifdef MAC
error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
&nd.ni_cnd);
@@ -3726,7 +3784,7 @@
else
vput(nd.ni_dvp);
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
- return (error);
+ goto fdout;
goto restart;
}
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
@@ -3739,6 +3797,9 @@
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
+fdout:
+ if (fp != NULL)
+ fdrop(fp, td);
return (error);
}
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -313,6 +313,16 @@
#define POSIX_FADV_NOREUSE 5 /* access data only once */
#endif
+
+#ifdef __BSD_VISIBLE
+/*
+ * Magic value that specify that corresponding file descriptor to filename
+ * is unknown and sanitary check should be omitted in the fdunlinkat() and
+ * similar syscalls.
+ */
+#define FD_NONE -100
+#endif
+
#ifndef _KERNEL
__BEGIN_DECLS
int open(const char *, int, ...);
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -216,7 +216,7 @@
enum uio_seg fromseg, struct mbuf **controlp);
int kern_renameat(struct thread *td, int oldfd, char *old, int newfd,
char *new, enum uio_seg pathseg);
-int kern_rmdirat(struct thread *td, int fd, char *path,
+int kern_fdrmdirat(struct thread *td, int dfd, const char *path, int fd,
enum uio_seg pathseg);
int kern_sched_getparam(struct thread *td, struct thread *targettd,
struct sched_param *param);
@@ -283,7 +283,7 @@
int kern_thr_suspend(struct thread *td, struct timespec *tsp);
int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg,
off_t length);
-int kern_unlinkat(struct thread *td, int fd, char *path,
+int kern_fdunlinkat(struct thread *td, int dfd, const char *path, int fd,
enum uio_seg pathseg, ino_t oldinum);
int kern_utimesat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg);
Index: sys/ufs/ffs/ffs_alloc.c
===================================================================
--- sys/ufs/ffs/ffs_alloc.c
+++ sys/ufs/ffs/ffs_alloc.c
@@ -3096,14 +3096,15 @@
}
#endif /* DEBUG */
/*
- * kern_unlinkat will do its own start/finish writes and
+ * kern_fdunlinkat will do its own start/finish writes and
* they do not nest, so drop ours here. Setting mp == NULL
* indicates that vn_finished_write is not needed down below.
*/
vn_finished_write(mp);
mp = NULL;
- error = kern_unlinkat(td, AT_FDCWD, (char *)(intptr_t)cmd.value,
- UIO_USERSPACE, (ino_t)cmd.size);
+ error = kern_fdunlinkat(td, AT_FDCWD,
+ (char *)(intptr_t)cmd.value, FD_NONE, UIO_USERSPACE,
+ (ino_t)cmd.size);
break;
case FFS_SET_INODE:

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 9, 8:22 AM (14 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16548958
Default Alt Text
D14567.id44045.diff (18 KB)

Event Timeline