Page MenuHomeFreeBSD

D43518.id133087.diff
No OneTemporary

D43518.id133087.diff

diff --git a/include/unistd.h b/include/unistd.h
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -519,6 +519,8 @@
int iruserok_sa(const void *, int, int, const char *, const char *);
int issetugid(void);
void __FreeBSD_libc_enter_restricted_mode(void);
+int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1,
+ unsigned long idx2);
long lpathconf(const char *, int);
#ifndef _MKDTEMP_DECLARED
char *mkdtemp(char *);
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -424,6 +424,10 @@
timerfd_settime;
};
+FBSD_1.8 {
+ kcmp;
+};
+
FBSDprivate_1.0 {
/* System call stubs */
___acl_aclcheck_fd;
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -1721,6 +1721,19 @@
return (minor(ldev->dev));
}
+static int
+linux_file_kcmp(struct file *fp1, struct file *fp2, struct thread *td)
+{
+ struct linux_file *filp1, *filp2;
+
+ if (fp2->f_type != DTYPE_DEV)
+ return (3);
+
+ filp1 = fp1->f_data;
+ filp2 = fp2->f_data;
+ return (kcmp_cmp((uintptr_t)filp1->f_cdev, (uintptr_t)filp2->f_cdev));
+}
+
struct fileops linuxfileops = {
.fo_read = linux_file_read,
.fo_write = linux_file_write,
@@ -1735,6 +1748,7 @@
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_cmp = linux_file_kcmp,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -2010,6 +2010,14 @@
return (cdev2priv(x)->cdp_inode);
}
+static int
+devfs_cmp_f(struct file *fp1, struct file *fp2, struct thread *td)
+{
+ if (fp2->f_type != DTYPE_VNODE || fp2->f_ops != &devfs_ops_f)
+ return (3);
+ return (kcmp_cmp((uintptr_t)fp1->f_data, (uintptr_t)fp2->f_data));
+}
+
static struct fileops devfs_ops_f = {
.fo_read = devfs_read_f,
.fo_write = devfs_write_f,
@@ -2025,6 +2033,7 @@
.fo_seek = vn_seek,
.fo_fill_kinfo = vn_fill_kinfo,
.fo_mmap = devfs_mmap_f,
+ .fo_cmp = devfs_cmp_f,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
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
@@ -2279,7 +2279,7 @@
* 3. after the lock is observed as not taken, any fdhold/pdhold calls are
* guaranteed to see NULL, making it safe to finish clearing
*/
-static struct filedesc *
+struct filedesc *
fdhold(struct proc *p)
{
struct filedesc *fdp;
@@ -2303,7 +2303,7 @@
return (pdp);
}
-static void
+void
fddrop(struct filedesc *fdp)
{
@@ -5253,6 +5253,7 @@
.fo_chown = badfo_chown,
.fo_sendfile = badfo_sendfile,
.fo_fill_kinfo = vn_fill_kinfo,
+ .fo_cmp = vn_cmp,
.fo_flags = DFLAG_PASSABLE,
};
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
@@ -139,6 +139,7 @@
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_cmp = file_kcmp_generic,
.fo_fill_kinfo = kqueue_fill_kinfo,
};
diff --git a/sys/kern/sys_eventfd.c b/sys/kern/sys_eventfd.c
--- a/sys/kern/sys_eventfd.c
+++ b/sys/kern/sys_eventfd.c
@@ -76,6 +76,7 @@
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = eventfd_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE
};
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
@@ -65,6 +65,7 @@
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/vnode.h>
+#include <sys/unistd.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/condvar.h>
@@ -2071,3 +2072,134 @@
td->td_retval[0] = error;
return (0);
}
+
+int
+kcmp_cmp(uintptr_t a, uintptr_t b)
+{
+ if (a == b)
+ return (0);
+ else if (a < b)
+ return (1);
+ return (2);
+}
+
+static int
+kcmp_pget(struct thread *td, pid_t pid, struct proc **pp)
+{
+ int error;
+ if (pid != td->td_proc->p_pid) {
+ error = pget(pid, PGET_CANDEBUG | PGET_NOTWEXIT | PGET_HOLD,
+ pp);
+ } else {
+ error = 0;
+ *pp = td->td_proc;
+ }
+ return (error);
+}
+
+static int
+kcmp_getfp(struct thread *td, struct proc *p, int fd, struct file **fpp)
+{
+ struct filedesc *fdp;
+ struct file *fp;
+ int error;
+
+ if (p == td->td_proc) /* curproc */
+ return (fget_unlocked(td, fd, &cap_no_rights, fpp));
+
+ PROC_LOCK(p);
+ fdp = fdhold(p);
+ PROC_UNLOCK(p);
+ fp = NULL;
+ if (fdp == NULL)
+ return (ENOENT);
+ error = 0;
+ FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) != 0) {
+ fp = fget_noref(fdp, fd);
+ if (fp != NULL && fhold(fp)) {
+ *fpp = fp;
+ } else {
+ error = EBADF;
+ }
+ } else {
+ error = ENOENT;
+ }
+ FILEDESC_SUNLOCK(fdp);
+ fddrop(fdp);
+ return (error);
+}
+
+int
+kern_kcmp(struct thread *td, pid_t pid1, pid_t pid2, int type,
+ unsigned long idx1, unsigned long idx2)
+{
+ struct proc *p1, *p2;
+ struct file *fp1, *fp2;
+ int error, res;
+
+ res = -1;
+ p1 = p2 = NULL;
+ error = kcmp_pget(td, pid1, &p1);
+ if (error == 0)
+ error = kcmp_pget(td, pid2, &p2);
+ if (error != 0)
+ goto out;
+
+ switch (type) {
+ case KCMP_FILE:
+ case KCMP_FILEOBJ:
+ error = kcmp_getfp(td, p1, idx1, &fp1);
+ if (error == 0) {
+ error = kcmp_getfp(td, p2, idx2, &fp2);
+ if (error == 0) {
+ if (type == KCMP_FILEOBJ)
+ res = fo_cmp(fp1, fp2, td);
+ else
+ res = kcmp_cmp((uintptr_t)fp1,
+ (uintptr_t)fp2);
+ fdrop(fp2, td);
+ }
+ fdrop(fp1, td);
+ }
+ break;
+ case KCMP_FILES:
+ res = kcmp_cmp((uintptr_t)p1->p_fd, (uintptr_t)p2->p_fd);
+ break;
+ case KCMP_SIGHAND:
+ res = kcmp_cmp((uintptr_t)p1->p_sigacts,
+ (uintptr_t)p2->p_sigacts);
+ break;
+ case KCMP_VM:
+ res = kcmp_cmp((uintptr_t)p1->p_vmspace,
+ (uintptr_t)p2->p_vmspace);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+out:
+ if (p1 != NULL && p1 != td->td_proc)
+ PRELE(p1);
+ if (p2 != NULL && p2 != td->td_proc)
+ PRELE(p2);
+
+ td->td_retval[0] = res;
+ return (error);
+}
+
+int
+sys_kcmp(struct thread *td, struct kcmp_args *uap)
+{
+ return (kern_kcmp(td, uap->pid1, uap->pid2, uap->type,
+ uap->idx1, uap->idx2));
+}
+
+int
+file_kcmp_generic(struct file *fp1, struct file *fp2, struct thread *td)
+{
+ if (fp1->f_type != fp2->f_type)
+ return (3);
+ return (kcmp_cmp((uintptr_t)fp1->f_data, (uintptr_t)fp2->f_data));
+}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -165,6 +165,7 @@
.fo_chown = pipe_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = pipe_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE
};
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
@@ -94,6 +94,7 @@
static fo_stat_t procdesc_stat;
static fo_close_t procdesc_close;
static fo_fill_kinfo_t procdesc_fill_kinfo;
+static fo_cmp_t procdesc_cmp;
static struct fileops procdesc_ops = {
.fo_read = invfo_rdwr,
@@ -108,6 +109,7 @@
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = procdesc_fill_kinfo,
+ .fo_cmp = procdesc_cmp,
.fo_flags = DFLAG_PASSABLE,
};
@@ -552,3 +554,15 @@
kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
return (0);
}
+
+static int
+procdesc_cmp(struct file *fp1, struct file *fp2, struct thread *td)
+{
+ struct procdesc *pdp1, *pdp2;
+
+ if (fp2->f_type != DTYPE_PROCDESC)
+ return (3);
+ pdp1 = fp1->f_data;
+ pdp2 = fp2->f_data;
+ return (kcmp_cmp((uintptr_t)pdp1->pd_pid, (uintptr_t)pdp2->pd_pid));
+}
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -109,6 +109,7 @@
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = soo_fill_kinfo,
.fo_aio_queue = soo_aio_queue,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE
};
diff --git a/sys/kern/sys_timerfd.c b/sys/kern/sys_timerfd.c
--- a/sys/kern/sys_timerfd.c
+++ b/sys/kern/sys_timerfd.c
@@ -371,6 +371,7 @@
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = timerfd_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3329,6 +3329,14 @@
_Out_opt_ _Contains_long_timet_ struct itimerspec *old_value
);
}
-
+588 AUE_NULL STD {
+ int kcmp(
+ pid_t pid1,
+ pid_t pid2,
+ int type,
+ unsigned long idx1,
+ unsigned long idx2
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -610,6 +610,7 @@
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = ptsdev_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -2661,6 +2661,7 @@
.fo_chown = mqf_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = mqf_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -153,6 +153,7 @@
.fo_chown = ksem_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = ksem_fill_kinfo,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE
};
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -169,6 +169,7 @@
.fo_add_seals = shm_add_seals,
.fo_fallocate = shm_fallocate,
.fo_fspacectl = shm_fspacectl,
+ .fo_cmp = file_kcmp_generic,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE,
};
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -123,6 +123,7 @@
.fo_mmap = vn_mmap,
.fo_fallocate = vn_fallocate,
.fo_fspacectl = vn_fspacectl,
+ .fo_cmp = vn_cmp,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -4228,3 +4229,11 @@
return (LK_SHARED);
return (LK_EXCLUSIVE);
}
+
+int
+vn_cmp(struct file *fp1, struct file *fp2, struct thread *td)
+{
+ if (fp2->f_type != DTYPE_VNODE)
+ return (3);
+ return (kcmp_cmp((uintptr_t)fp1->f_vnode, (uintptr_t)fp2->f_vnode));
+}
diff --git a/sys/sys/file.h b/sys/sys/file.h
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -129,6 +129,7 @@
typedef int fo_fspacectl_t(struct file *fp, int cmd,
off_t *offset, off_t *length, int flags,
struct ucred *active_cred, struct thread *td);
+typedef int fo_cmp_t(struct file *fp, struct file *fp1, struct thread *td);
typedef int fo_spare_t(struct file *fp);
typedef int fo_flags_t;
@@ -152,6 +153,7 @@
fo_get_seals_t *fo_get_seals;
fo_fallocate_t *fo_fallocate;
fo_fspacectl_t *fo_fspacectl;
+ fo_cmp_t *fo_cmp;
fo_spare_t *fo_spares[8]; /* Spare slots */
fo_flags_t fo_flags; /* DFLAG_* below */
};
@@ -276,6 +278,7 @@
fo_fill_kinfo_t vn_fill_kinfo;
fo_kqfilter_t vn_kqfilter_opath;
int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif);
+int file_kcmp_generic(struct file *fp1, struct file *fp2, struct thread *td);
void finit(struct file *, u_int, short, void *, struct fileops *);
void finit_vnode(struct file *, u_int, void *, struct fileops *);
@@ -489,6 +492,14 @@
active_cred, td));
}
+static __inline int
+fo_cmp(struct file *fp1, struct file *fp2, struct thread *td)
+{
+
+ if (fp1->f_ops->fo_cmp == NULL)
+ return (EBADF);
+ return ((*fp1->f_ops->fo_cmp)(fp1, fp2, td));
+}
#endif /* _KERNEL */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -262,6 +262,8 @@
void fdclose(struct thread *td, struct file *fp, int idx);
void fdcloseexec(struct thread *td);
void fdsetugidsafety(struct thread *td);
+struct filedesc *fdhold(struct proc *p);
+void fddrop(struct filedesc *fdp);
struct filedesc *fdcopy(struct filedesc *fdp);
void fdunshare(struct thread *td);
void fdescfree(struct thread *td);
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -198,6 +198,8 @@
int kern_jail(struct thread *td, struct jail *j);
int kern_jail_get(struct thread *td, struct uio *options, int flags);
int kern_jail_set(struct thread *td, struct uio *options, int flags);
+int kern_kcmp(struct thread *td, pid_t pid1, pid_t pid2, int type,
+ unsigned long idx1, unsigned long idx2);
int kern_kevent(struct thread *td, int fd, int nchanges, int nevents,
struct kevent_copyops *k_ops, const struct timespec *timeout);
int kern_kevent_anonymous(struct thread *td, int nevents,
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -485,6 +485,8 @@
/* XXX: Should be void nanodelay(u_int nsec); */
void DELAY(int usec);
+int kcmp_cmp(uintptr_t a, uintptr_t b);
+
/* Root mount holdback API */
struct root_hold_token {
int flags;
diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h
--- a/sys/sys/unistd.h
+++ b/sys/sys/unistd.h
@@ -195,6 +195,13 @@
RFPROCDESC | RFSPAWN | RFPPWAIT)
#define RFKERNELONLY (RFSTOPPED | RFHIGHPID | RFPROCDESC)
+/* kcmp() options. */
+#define KCMP_FILE 100
+#define KCMP_FILEOBJ 101
+#define KCMP_FILES 102
+#define KCMP_SIGHAND 103
+#define KCMP_VM 104
+
#define SWAPOFF_FORCE 0x00000001
/*
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -818,6 +818,7 @@
void *alloc_arg, int lkflags, struct vnode **rvp);
int vn_utimes_perm(struct vnode *vp, struct vattr *vap,
struct ucred *cred, struct thread *td);
+int vn_cmp(struct file *, struct file *, struct thread *td);
int vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio);
int vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 25, 5:43 PM (13 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16157090
Default Alt Text
D43518.id133087.diff (13 KB)

Event Timeline