Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108432650
D43518.id133087.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D43518.id133087.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D43518: Implement kcmp(2)
Attached
Detach File
Event Timeline
Log In to Comment