Page MenuHomeFreeBSD

D14567.id39889.diff
No OneTemporary

D14567.id39889.diff

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;
+ unlinkfd;
};
FBSDprivate_1.0 {
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1123,5 +1123,6 @@
cpuwhich_t which, uint32_t id1, uint32_t id2, \
size_t domainsetsize, domainset_t *mask, \
int policy); }
+563 AUE_NULL STD { int unlinkfd(int fd, char *path); }
; vim: syntax=off
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -463,6 +463,7 @@
renameat
symlinkat
unlinkat
+unlinkfd
utimensat
##
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -1027,6 +1027,7 @@
cpuwhich_t which, id_t id, \
size_t domainsetsize, domainset_t *mask, \
int policy); }
+563 AUE_NULL STD { int unlinkfd(int fd, char *path); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -1763,11 +1763,53 @@
return (kern_unlinkat(td, fd, path, UIO_USERSPACE, 0));
}
+static int
+unlink_vnode(struct thread *td, struct nameidata *nd, struct vnode *vp)
+{
+ int error;
+ struct mount *mp;
+
+ /*
+ * The root of a mounted filesystem cannot be deleted.
+ *
+ * XXX: can this only be a VDIR case?
+ */
+ if (vp->v_vflag & VV_ROOT) {
+ error = EBUSY;
+ } else {
+ if (vn_start_write(nd->ni_dvp, &mp, V_NOWAIT) != 0) {
+ NDFREE(nd, NDF_ONLY_PNBUF);
+ vput(nd->ni_dvp);
+ if (vp == nd->ni_dvp)
+ vrele(vp);
+ else
+ vput(vp);
+ if ((error = vn_start_write(NULL, &mp,
+ V_XSLEEP | PCATCH)) != 0)
+ return (error);
+ return (EINTR);
+ }
+#ifdef MAC
+ error = mac_vnode_check_unlink(td->td_ucred, nd->ni_dvp, vp,
+ &nd->ni_cnd);
+ if (error != 0)
+ goto out;
+#endif
+ vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
+ error = VOP_REMOVE(nd->ni_dvp, vp, &nd->ni_cnd);
+#ifdef MAC
+out:
+#endif
+ vn_finished_write(mp);
+ }
+
+ return (error);
+}
+
int
kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
ino_t oldinum)
{
- struct mount *mp;
struct vnode *vp;
struct nameidata nd;
struct stat sb;
@@ -1787,41 +1829,14 @@
((error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td)) == 0) &&
sb.st_ino != oldinum) {
error = EIDRM; /* Identifier removed */
- } else {
- /*
- * The root of a mounted filesystem cannot be deleted.
- *
- * XXX: can this only be a VDIR case?
- */
- if (vp->v_vflag & VV_ROOT)
- error = EBUSY;
}
+
if (error == 0) {
- if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vput(nd.ni_dvp);
- if (vp == nd.ni_dvp)
- vrele(vp);
- else
- vput(vp);
- if ((error = vn_start_write(NULL, &mp,
- V_XSLEEP | PCATCH)) != 0)
- return (error);
+ error = unlink_vnode(td, &nd, vp);
+ if (error == EINTR)
goto restart;
- }
-#ifdef MAC
- error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
- &nd.ni_cnd);
- if (error != 0)
- goto out;
-#endif
- vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
- error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
-#ifdef MAC
-out:
-#endif
- vn_finished_write(mp);
}
+
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
if (vp == nd.ni_dvp)
@@ -1831,6 +1846,68 @@
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct unlinkfd_args {
+ int fd;
+ char *path;
+};
+#endif
+int
+sys_unlinkfd(struct thread *td, struct unlinkfd_args *uap)
+{
+ int fd = uap->fd;
+ char *path = uap->path;
+
+ return (kern_unlinkfd(td, fd, path));
+}
+
+int
+kern_unlinkfd(struct thread *td, int fd, char *path)
+{
+ struct nameidata nd;
+ struct file *fp;
+ struct vnode *vfdp, *vp;
+ cap_rights_t rights;
+ int error;
+
+ error = getvnode(td, fd, cap_rights_init(&rights, CAP_UNLINKFD), &fp);
+ if (error != 0)
+ return (error);
+ vfdp = fp->f_vnode;
+
+ if (vfdp->v_type == VDIR) {
+ error = EPERM;
+ goto out;
+ }
+
+restart:
+ bwillwrite();
+ NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ path, td);
+ error = namei(&nd);
+ if (error != 0) {
+ if (error == EINVAL)
+ error = EPERM;
+ goto out;
+ }
+ vp = nd.ni_vp;
+ if (error == 0) {
+ if (vfdp == vp) {
+ error = unlink_vnode(td, &nd, vp);
+ if (error == EINTR)
+ goto restart;
+ } else {
+ error = EINVAL;
+ }
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vput(nd.ni_dvp);
+ vput(vp);
+out:
+ fdrop(fp, td);
+ return (error);
+}
+
/*
* Reposition read/write file offset.
*/
Index: sys/sys/capsicum.h
===================================================================
--- sys/sys/capsicum.h
+++ sys/sys/capsicum.h
@@ -169,6 +169,8 @@
* will be removed.
*/
#define CAP_UNLINKAT (CAP_LOOKUP | 0x0000000010000000ULL)
+/* Allows unlinkfd. */
+#define CAP_UNLINKFD (CAP_LOOKUP | 0x0000080000000000ULL)
/* Socket operations. */
/* Allows for accept(2) and accept4(2). */
@@ -213,10 +215,10 @@
CAP_SETSOCKOPT | CAP_SHUTDOWN)
/* All used bits for index 0. */
-#define CAP_ALL0 CAPRIGHT(0, 0x000007FFFFFFFFFFULL)
+#define CAP_ALL0 CAPRIGHT(0, 0x00000FFFFFFFFFFFULL)
/* Available bits for index 0. */
-#define CAP_UNUSED0_44 CAPRIGHT(0, 0x0000080000000000ULL)
+#define CAP_UNUSED0_45 CAPRIGHT(0, 0x0000100000000000ULL)
/* ... */
#define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL)
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -285,6 +285,7 @@
off_t length);
int kern_unlinkat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, ino_t oldinum);
+int kern_unlinkfd(struct thread *td, int fd, char *path);
int kern_utimesat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg);
int kern_utimensat(struct thread *td, int fd, char *path,

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 11, 4:03 PM (1 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25123062
Default Alt Text
D14567.id39889.diff (6 KB)

Event Timeline