Page MenuHomeFreeBSD

D57163.diff
No OneTemporary

D57163.diff

diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -500,7 +500,8 @@
pdfork.2 pdopenpid.2 \
pdfork.2 pdkill.2 \
pdfork.2 pdrfork.2 \
- pdfork.2 pdwait.2
+ pdfork.2 pdwait.2 \
+ pdfork.2 pddupfd.2
MLINKS+=pipe.2 pipe2.2
MLINKS+=poll.2 ppoll.2
MLINKS+=rctl_add_rule.2 rctl_get_limits.2 \
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -391,6 +391,7 @@
};
FBSD_1.9 {
+ pddupfd;
pdopenpid;
pdrfork;
pdrfork_thread;
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -476,6 +476,7 @@
typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
typedef int (__sys_pdopenpid_t)(pid_t, int);
+typedef int (__sys_pddupfd_t)(int, int, int);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -887,6 +888,7 @@
int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
int __sys_pdopenpid(pid_t pid, int flags);
+int __sys_pddupfd(int pd, int fd, int flags);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/pdfork.2 b/lib/libsys/pdfork.2
--- a/lib/libsys/pdfork.2
+++ b/lib/libsys/pdfork.2
@@ -39,7 +39,8 @@
.Nm pdopenpid ,
.Nm pdgetpid ,
.Nm pdkill ,
-.Nm pdwait
+.Nm pdwait ,
+.Nm pddupfd
.Nd System calls to manage process descriptors
.Sh LIBRARY
.Lb libc
@@ -63,6 +64,8 @@
.Fa "struct __wrusage *wrusage"
.Fa "struct __siginfo *info"
.Fc
+.Ft int
+.Fn pddupfd "int fd" "int remotefd" "int flags"
.Sh DESCRIPTION
Process descriptors are special file descriptors that represent processes,
and are created using
@@ -168,6 +171,23 @@
.Xr wait6
system call for the behavior specification.
.Pp
+The
+.Fn pddupfd
+allows the caller to duplicate a file descriptor across the process
+boundaries.
+The function returns the new file descriptor that points to the same file
+as the file descriptor
+.Fa remotefd
+in the process specified by the
+.Fa fd
+process descriptor.
+The returned file descriptor has the
+.Va O_CLOEXEC
+flag set.
+The
+.Fa flags
+argument is reserved and must be zero.
+.Pp
The following system calls also have effects specific to process descriptors:
.Pp
.Xr fstat 2
@@ -220,8 +240,9 @@
.Fn pdopenpid ,
.Fn pdgetpid ,
.Fn pdkill ,
+.Fn pdwait ,
and
-.Fn pdwait
+.Fn pddupfd
return 0 on success and -1 on failure.
.Sh ERRORS
These functions may return the same error numbers as their PID-based equivalents
@@ -289,6 +310,30 @@
argument does not exist, or the caller does not have enough privileges
to open the process.
.El
+.Pp
+The
+.Fn pddupfd
+returns the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa flags
+argument is not zero.
+.It Bq Er ESRCH
+The process specified by the file descriptor
+.Fa fd
+exited.
+.It Bq Er EBADF
+The file descriptor
+.Fa fd
+is not a process file descriptor.
+.It Bq Er EBADF
+The file descriptor
+.Fa remotefd
+is not a valid file descriptor in the specified process.
+.It Bq Er ENOENT
+The specified process does not have a file descriptor table.
+.El
.Sh SEE ALSO
.Xr close 2 ,
.Xr fork 2 ,
@@ -315,7 +360,9 @@
.Fx 15.1 .
The
.Fn pdopenpid
-system call first appeared in
+and
+.Fn pddupfd
+system calls first appeared in
.Fx 16.0 .
.Pp
Support for process descriptors mode was developed as part of the
@@ -339,5 +386,7 @@
.An Alan Somers Aq Mt asomers@FreeBSD.org .
The
.Fn pdopenpid
-function was developed by
+and
+.Fn pddupfd
+functions were developed by
.An Konstantin Belousov Aq Mt kib@FreeBSD.org .
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -827,4 +827,6 @@
__sys_renameat2;
_pdopenpid;
__sys_pdopenpid;
+ _pddupfd;
+ __sys_pddupfd;
};
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -521,4 +521,5 @@
#define FREEBSD32_SYS_freebsd32_pdwait 601
#define FREEBSD32_SYS_renameat2 602
#define FREEBSD32_SYS_pdopenpid 603
-#define FREEBSD32_SYS_MAXSYSCALL 604
+#define FREEBSD32_SYS_pddupfd 604
+#define FREEBSD32_SYS_MAXSYSCALL 605
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -609,4 +609,5 @@
"freebsd32_pdwait", /* 601 = freebsd32_pdwait */
"renameat2", /* 602 = renameat2 */
"pdopenpid", /* 603 = pdopenpid */
+ "pddupfd", /* 604 = pddupfd */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -671,4 +671,5 @@
{ .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
+ { .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3466,6 +3466,15 @@
*n_args = 2;
break;
}
+ /* pddupfd */
+ case 604: {
+ struct pddupfd_args *p = params;
+ iarg[a++] = p->pd; /* int */
+ iarg[a++] = p->fd; /* int */
+ iarg[a++] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9368,6 +9377,22 @@
break;
};
break;
+ /* pddupfd */
+ case 604:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11306,6 +11331,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* pddupfd */
+ case 604:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -670,4 +670,5 @@
{ .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
+ { .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
};
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3156,13 +3156,20 @@
#endif
int
-fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp)
+fget_remote(struct thread *td, struct proc *p, int fd, struct filecaps *fcaps,
+ uint8_t *fd_flags, struct file **fpp)
{
struct filedesc *fdp;
struct file *fp;
int error;
- if (p == td->td_proc) /* curproc */
+ /*
+ * Both fcaps and fd_flags must be either requested together,
+ * or not at all.
+ */
+ MPASS((!(fcaps == NULL) ^ (fd_flags == NULL)));
+
+ if (p == td->td_proc && fcaps == NULL) /* curproc */
return (fget_unlocked(td, fd, &cap_no_rights, fpp));
PROC_LOCK(p);
@@ -3175,6 +3182,9 @@
fp = fget_noref(fdp, fd);
if (fp != NULL && fhold(fp)) {
*fpp = fp;
+ *fd_flags = fde_to_fd_flags(fdp->fd_ofiles[fd].
+ fde_flags);
+ *fcaps = fdp->fd_ofiles[fd].fde_caps;
error = 0;
} else {
error = EBADF;
@@ -3215,7 +3225,7 @@
}
for (fd = 0; fd <= highfd; fd++) {
- error1 = fget_remote(td, p, fd, &fp);
+ error1 = fget_remote(td, p, fd, NULL, NULL, &fp);
if (error1 != 0)
continue;
error = fn(p, fd, fp, arg);
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -3354,7 +3354,7 @@
struct kqueue *kq;
int error;
- error = fget_remote(td, p, kq_fd, &fp);
+ error = fget_remote(td, p, kq_fd, NULL, NULL, &fp);
if (error == 0) {
if (fp->f_type != DTYPE_KQUEUE) {
error = EINVAL;
diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c
--- a/sys/kern/subr_capability.c
+++ b/sys/kern/subr_capability.c
@@ -88,6 +88,7 @@
const cap_rights_t cap_mkdirat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKDIRAT);
const cap_rights_t cap_mkfifoat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKFIFOAT);
const cap_rights_t cap_mknodat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKNODAT);
+const cap_rights_t cap_pddupfd_rights = CAP_RIGHTS_INITIALIZER(CAP_PDDUPFD);
const cap_rights_t cap_pdgetpid_rights = CAP_RIGHTS_INITIALIZER(CAP_PDGETPID);
const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL);
const cap_rights_t cap_pdwait_rights = CAP_RIGHTS_INITIALIZER(CAP_PDWAIT);
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -2185,9 +2185,9 @@
switch (type) {
case KCMP_FILE:
case KCMP_FILEOBJ:
- error = fget_remote(td, p1, idx1, &fp1);
+ error = fget_remote(td, p1, idx1, NULL, NULL, &fp1);
if (error == 0) {
- error = fget_remote(td, p2, idx2, &fp2);
+ error = fget_remote(td, p2, idx2, NULL, NULL, &fp2);
if (error == 0) {
if (type == KCMP_FILEOBJ)
res = fo_cmp(fp1, fp2, td);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -662,3 +662,62 @@
return (EINVAL);
return (kern_pdopenpid(td, args->pid, args->flags));
}
+
+static int
+kern_pddupfd(struct thread *td, int pdfd, int fd, int flags)
+{
+ struct proc *p;
+ struct file *fp, *pfp;
+ struct procdesc *pd;
+ struct filecaps fcaps;
+ uint8_t fd_flags;
+ int error, fdr;
+
+ error = fget(td, pdfd, &cap_pddupfd_rights, &pfp);
+ if (error != 0)
+ return (error);
+ if (pfp->f_type != DTYPE_PROCDESC) {
+ error = EBADF;
+ goto out;
+ }
+ pd = pfp->f_data;
+ sx_slock(&proctree_lock);
+ p = pd->pd_proc;
+ if (p != NULL) {
+ AUDIT_ARG_PROCESS(p);
+ PROC_LOCK(p);
+ if ((p->p_flag & P_WEXIT) != 0)
+ error = ESRCH;
+ else
+ _PHOLD(p);
+ PROC_UNLOCK(p);
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto out;
+
+ error = fget_remote(td, p, fd, &fcaps, &fd_flags, &fp);
+ PRELE(p);
+ if (error == 0) {
+ error = finstall_refed(td, fp, &fdr, O_CLOEXEC |
+ ((fd_flags & FD_RESOLVE_BENEATH) != 0 ?
+ O_RESOLVE_BENEATH : 0), &fcaps);
+ if (error != 0)
+ fdrop(fp, td);
+ else
+ td->td_retval[0] = fdr;
+ }
+ } else {
+ sx_sunlock(&proctree_lock);
+ }
+out:
+ fdrop(pfp, td);
+ return (error);
+}
+
+int
+sys_pddupfd(struct thread *td, struct pddupfd_args *args)
+{
+ if (args->flags != 0)
+ return (EINVAL);
+ return (kern_pddupfd(td, args->pd, args->fd, args->flags));
+}
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -609,4 +609,5 @@
"pdwait", /* 601 = pdwait */
"renameat2", /* 602 = renameat2 */
"pdopenpid", /* 603 = pdopenpid */
+ "pddupfd", /* 604 = pddupfd */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3435,5 +3435,12 @@
int flags
);
}
+604 AUE_NULL STD {
+ int pddupfd(
+ int pd,
+ int fd,
+ int flags
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3563,6 +3563,15 @@
*n_args = 2;
break;
}
+ /* pddupfd */
+ case 604: {
+ struct pddupfd_args *p = params;
+ iarg[a++] = p->pd; /* int */
+ iarg[a++] = p->fd; /* int */
+ iarg[a++] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9542,6 +9551,22 @@
break;
};
break;
+ /* pddupfd */
+ case 604:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11575,6 +11600,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* pddupfd */
+ case 604:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h
--- a/sys/sys/caprights.h
+++ b/sys/sys/caprights.h
@@ -90,6 +90,7 @@
extern const cap_rights_t cap_mknodat_rights;
extern const cap_rights_t cap_mmap_rights;
extern const cap_rights_t cap_no_rights;
+extern const cap_rights_t cap_pddupfd_rights;
extern const cap_rights_t cap_pdgetpid_rights;
extern const cap_rights_t cap_pdkill_rights;
extern const cap_rights_t cap_pdwait_rights;
diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h
--- a/sys/sys/capsicum.h
+++ b/sys/sys/capsicum.h
@@ -244,12 +244,7 @@
/* Process management via process descriptors. */
/* Allows for pdgetpid(2). */
#define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL)
-/*
- * Allows for pdwait4(2).
- *
- * XXX: this constant was imported unused, but is targeted to be implemented
- * in the future (bug 235871).
- */
+/* Allows for pdwait(2). */
#define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL)
/* Allows for pdkill(2). */
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
@@ -283,12 +278,13 @@
#define CAP_INOTIFY_ADD CAPRIGHT(1, 0x0000000000200000ULL)
#define CAP_INOTIFY_RM CAPRIGHT(1, 0x0000000000400000ULL)
+/* Allows pdgetfd(2). */
+#define CAP_PDDUPFD CAPRIGHT(1, 0x0000000000800000ULL)
+
/* All used bits for index 1. */
-#define CAP_ALL1 CAPRIGHT(1, 0x00000000007FFFFFULL)
+#define CAP_ALL1 CAPRIGHT(1, 0x0000000000FFFFFFULL)
/* Available bits for index 1. */
-#define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000800000ULL)
-/* ... */
#define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL)
/* Backward compatibility. */
diff --git a/sys/sys/file.h b/sys/sys/file.h
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -281,7 +281,8 @@
int fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp,
int needfcntl, struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
-int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp);
+int fget_remote(struct thread *td, struct proc *p, int fd,
+ struct filecaps *fcaps, uint8_t *fd_flags, struct file **fpp);
int fget_remote_foreach(struct thread *td, struct proc *p,
int (*fn)(struct proc *, int, struct file *, void *), void *arg);
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -130,6 +130,7 @@
int pdgetpid(int, pid_t *);
int pdopenpid(pid_t, int);
int pdwait(int, int *, int, struct __wrusage *, struct __siginfo *);
+int pddupfd(int, int, int);
pid_t pdrfork_thread(int *, int, int, void *, int (*)(void *), void *);
__END_DECLS
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -542,4 +542,5 @@
#define SYS_pdwait 601
#define SYS_renameat2 602
#define SYS_pdopenpid 603
-#define SYS_MAXSYSCALL 604
+#define SYS_pddupfd 604
+#define SYS_MAXSYSCALL 605
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -445,4 +445,5 @@
pdrfork.o \
pdwait.o \
renameat2.o \
- pdopenpid.o
+ pdopenpid.o \
+ pddupfd.o
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1936,6 +1936,11 @@
char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
+struct pddupfd_args {
+ char pd_l_[PADL_(int)]; int pd; char pd_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2347,6 +2352,7 @@
int sys_pdwait(struct thread *, struct pdwait_args *);
int sys_renameat2(struct thread *, struct renameat2_args *);
int sys_pdopenpid(struct thread *, struct pdopenpid_args *);
+int sys_pddupfd(struct thread *, struct pddupfd_args *);
#ifdef COMPAT_43
@@ -3350,6 +3356,7 @@
#define SYS_AUE_pdwait AUE_PDWAIT
#define SYS_AUE_renameat2 AUE_RENAMEAT
#define SYS_AUE_pdopenpid AUE_PDOPENPID
+#define SYS_AUE_pddupfd AUE_NULL
#undef PAD_
#undef PADL_

File Metadata

Mime Type
text/plain
Expires
Tue, May 26, 8:06 PM (7 m, 4 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33517812
Default Alt Text
D57163.diff (17 KB)

Event Timeline