Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109685456
D14567.id44045.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D14567.id44045.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D14567: Introduce funlinkat.
Attached
Detach File
Event Timeline
Log In to Comment