mirror of https://github.com/NetBSD/src.git
procfs: Support sysvipc/{msg,sem,shm} used by linux
parent
b129f29edd
commit
02571cb3a8
|
@ -111,7 +111,11 @@ typedef enum {
|
|||
PFSstat, /* process status (if -o linux) */
|
||||
PFSstatm, /* process memory info (if -o linux) */
|
||||
PFSstatus, /* process status */
|
||||
PFStask, /* task subdirector (if -o linux) */
|
||||
PFSsysvipc, /* sysvipc subdirectory (if -o linux) */
|
||||
PFSsysvipc_msg, /* sysvipc msg info (if -o linux) */
|
||||
PFSsysvipc_sem, /* sysvipc sem info (if -o linux) */
|
||||
PFSsysvipc_shm, /* sysvipc shm info (if -o linux) */
|
||||
PFStask, /* task subdirectory (if -o linux) */
|
||||
PFSuptime, /* elapsed time since (if -o linux) */
|
||||
PFSversion, /* kernel version (if -o linux) */
|
||||
#ifdef __HAVE_PROCFS_MACHDEP
|
||||
|
@ -269,6 +273,12 @@ int procfs_doauxv(struct lwp *, struct proc *, struct pfsnode *,
|
|||
struct uio *);
|
||||
int procfs_dolimit(struct lwp *, struct proc *, struct pfsnode *,
|
||||
struct uio *);
|
||||
int procfs_dosysvipc_msg(struct lwp *, struct proc *, struct pfsnode *,
|
||||
struct uio *);
|
||||
int procfs_dosysvipc_sem(struct lwp *, struct proc *, struct pfsnode *,
|
||||
struct uio *);
|
||||
int procfs_dosysvipc_shm(struct lwp *, struct proc *, struct pfsnode *,
|
||||
struct uio *);
|
||||
|
||||
void procfs_hashrem(struct pfsnode *);
|
||||
int procfs_getfp(struct pfsnode *, struct proc *, struct file **);
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.87 2020/09/05 16:30:12 riastradh Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_sysv.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/atomic.h>
|
||||
|
@ -58,6 +62,15 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.87 2020/09/05 16:30:12 riastradh
|
|||
#include <sys/sysctl.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/filedesc.h>
|
||||
#ifdef SYSVMSG
|
||||
#include <sys/msg.h>
|
||||
#endif
|
||||
#ifdef SYSVSEM
|
||||
#include <sys/sem.h>
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
|
||||
|
@ -746,3 +759,141 @@ out:
|
|||
sysctl_unlock();
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_dosysvipc_msg(struct lwp *curl, struct proc *p,
|
||||
struct pfsnode *pfs, struct uio *uio)
|
||||
{
|
||||
char *bf;
|
||||
int offset = 0;
|
||||
int error = EFBIG;
|
||||
|
||||
bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
|
||||
|
||||
offset += snprintf(bf, LBFSZ,
|
||||
"%10s %10s %4s %10s %10s %5s %5s %5s %5s %5s %5s %10s %10s %10s\n",
|
||||
"key", "msqid", "perms", "cbytes", "qnum", "lspid", "lrpid",
|
||||
"uid", "gid", "cuid", "cgid", "stime", "rtime", "ctime");
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
|
||||
#ifdef SYSVMSG
|
||||
for (int id = 0; id < msginfo.msgmni; id++)
|
||||
if (msqs[id].msq_u.msg_qbytes > 0) {
|
||||
offset += snprintf(&bf[offset], LBFSZ - offset,
|
||||
"%10d %10d %4o %10zu %10lu %5u %5u %5u %5u %5u %5u %10lld %10lld %10lld\n",
|
||||
(int) msqs[id].msq_u.msg_perm._key,
|
||||
IXSEQ_TO_IPCID(id, msqs[id].msq_u.msg_perm),
|
||||
msqs[id].msq_u.msg_perm.mode,
|
||||
msqs[id].msq_u._msg_cbytes,
|
||||
msqs[id].msq_u.msg_qnum,
|
||||
msqs[id].msq_u.msg_lspid,
|
||||
msqs[id].msq_u.msg_lrpid,
|
||||
msqs[id].msq_u.msg_perm.uid,
|
||||
msqs[id].msq_u.msg_perm.gid,
|
||||
msqs[id].msq_u.msg_perm.cuid,
|
||||
msqs[id].msq_u.msg_perm.cgid,
|
||||
(long long)msqs[id].msq_u.msg_stime,
|
||||
(long long)msqs[id].msq_u.msg_rtime,
|
||||
(long long)msqs[id].msq_u.msg_ctime);
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = uiomove_frombuf(bf, offset, uio);
|
||||
out:
|
||||
free(bf, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_dosysvipc_sem(struct lwp *curl, struct proc *p,
|
||||
struct pfsnode *pfs, struct uio *uio)
|
||||
{
|
||||
char *bf;
|
||||
int offset = 0;
|
||||
int error = EFBIG;
|
||||
|
||||
bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
|
||||
|
||||
offset += snprintf(bf, LBFSZ,
|
||||
"%10s %10s %4s %10s %5s %5s %5s %5s %10s %10s\n",
|
||||
"key", "semid", "perms", "nsems", "uid", "gid", "cuid", "cgid",
|
||||
"otime", "ctime");
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
|
||||
#ifdef SYSVSEM
|
||||
for (int id = 0; id < seminfo.semmni; id++)
|
||||
if ((sema[id].sem_perm.mode & SEM_ALLOC) != 0) {
|
||||
offset += snprintf(&bf[offset], LBFSZ - offset,
|
||||
"%10d %10d %4o %10u %5u %5u %5u %5u %10lld %10lld\n",
|
||||
(int) sema[id].sem_perm._key,
|
||||
IXSEQ_TO_IPCID(id, sema[id].sem_perm),
|
||||
sema[id].sem_perm.mode,
|
||||
sema[id].sem_nsems,
|
||||
sema[id].sem_perm.uid,
|
||||
sema[id].sem_perm.gid,
|
||||
sema[id].sem_perm.cuid,
|
||||
sema[id].sem_perm.cgid,
|
||||
(long long)sema[id].sem_otime,
|
||||
(long long)sema[id].sem_ctime);
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = uiomove_frombuf(bf, offset, uio);
|
||||
out:
|
||||
free(bf, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_dosysvipc_shm(struct lwp *curl, struct proc *p,
|
||||
struct pfsnode *pfs, struct uio *uio)
|
||||
{
|
||||
char *bf;
|
||||
int offset = 0;
|
||||
int error = EFBIG;
|
||||
|
||||
bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
|
||||
|
||||
offset += snprintf(bf, LBFSZ,
|
||||
"%10s %10s %s %21s %5s %5s %5s %5s %5s %5s %5s %10s %10s %10s %21s %21s\n",
|
||||
"key", "shmid", "perms", "size", "cpid", "lpid", "nattch", "uid",
|
||||
"gid", "cuid", "cgid", "atime", "dtime", "ctime", "rss", "swap");
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
|
||||
#ifdef SYSVSHM
|
||||
for (unsigned int id = 0; id < shminfo.shmmni; id++)
|
||||
if ((shmsegs[id].shm_perm.mode & SHMSEG_ALLOCATED) != 0) {
|
||||
offset += snprintf(&bf[offset], LBFSZ - offset,
|
||||
"%10d %10d %4o %21zu %5u %5u %5u %5u %5u %5u %5u %10lld %10lld %10lld %21d %21d\n",
|
||||
(int) shmsegs[id].shm_perm._key,
|
||||
IXSEQ_TO_IPCID(id, shmsegs[id].shm_perm),
|
||||
shmsegs[id].shm_perm.mode,
|
||||
shmsegs[id].shm_segsz,
|
||||
shmsegs[id].shm_cpid,
|
||||
shmsegs[id].shm_lpid,
|
||||
shmsegs[id].shm_nattch,
|
||||
shmsegs[id].shm_perm.uid,
|
||||
shmsegs[id].shm_perm.gid,
|
||||
shmsegs[id].shm_perm.cuid,
|
||||
shmsegs[id].shm_perm.cgid,
|
||||
(long long)shmsegs[id].shm_atime,
|
||||
(long long)shmsegs[id].shm_dtime,
|
||||
(long long)shmsegs[id].shm_ctime,
|
||||
0, 0); /* XXX rss & swp are not supported */
|
||||
if (offset >= LBFSZ)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = uiomove_frombuf(bf, offset, uio);
|
||||
out:
|
||||
free(bf, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -283,6 +283,18 @@ procfs_rw(void *v)
|
|||
error = procfs_doauxv(curl, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case PFSsysvipc_msg:
|
||||
error = procfs_dosysvipc_msg(curl, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case PFSsysvipc_sem:
|
||||
error = procfs_dosysvipc_sem(curl, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case PFSsysvipc_shm:
|
||||
error = procfs_dosysvipc_shm(curl, p, pfs, uio);
|
||||
break;
|
||||
|
||||
#ifdef __HAVE_PROCFS_MACHDEP
|
||||
PROCFS_MACHDEP_NODETYPE_CASES
|
||||
error = procfs_machdep_rw(curl, l, pfs, uio);
|
||||
|
|
|
@ -436,6 +436,21 @@ procfs_loadvnode(struct mount *mp, struct vnode *vp,
|
|||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case PFSsysvipc:/* /proc/sysvipc = dr-xr-xr-x */
|
||||
if (pfs->pfs_fd == -1) {
|
||||
pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
|
||||
S_IROTH|S_IXOTH;
|
||||
vp->v_type = VDIR;
|
||||
break;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
case PFSsysvipc_msg: /* /proc/sysvipc/msg = -r--r--r-- */
|
||||
case PFSsysvipc_sem: /* /proc/sysvipc/sem = -r--r--r-- */
|
||||
case PFSsysvipc_shm: /* /proc/sysvipc/shm = -r--r--r-- */
|
||||
pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
#ifdef __HAVE_PROCFS_MACHDEP
|
||||
PROCFS_MACHDEP_NODETYPE_CASES
|
||||
procfs_machdep_allocvp(vp);
|
||||
|
|
|
@ -202,11 +202,28 @@ static const struct proc_target proc_root_targets[] = {
|
|||
{ DT_REG, N("stat"), PFScpustat, procfs_validfile_linux },
|
||||
{ DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux },
|
||||
{ DT_REG, N("version"), PFSversion, procfs_validfile_linux },
|
||||
{ DT_DIR, N("sysvipc"), PFSsysvipc, procfs_validfile_linux },
|
||||
#undef N
|
||||
};
|
||||
static const int nproc_root_targets =
|
||||
sizeof(proc_root_targets) / sizeof(proc_root_targets[0]);
|
||||
|
||||
/*
|
||||
* List of files in the sysvipc directory
|
||||
*/
|
||||
static const struct proc_target proc_sysvipc_targets[] = {
|
||||
#define N(s) sizeof(s)-1, s
|
||||
/* name type validp */
|
||||
{ DT_DIR, N("."), PFSsysvipc, NULL },
|
||||
{ DT_DIR, N(".."), PFSroot, NULL },
|
||||
{ DT_REG, N("msg"), PFSsysvipc_msg, procfs_validfile_linux },
|
||||
{ DT_REG, N("sem"), PFSsysvipc_sem, procfs_validfile_linux },
|
||||
{ DT_REG, N("shm"), PFSsysvipc_shm, procfs_validfile_linux },
|
||||
#undef N
|
||||
};
|
||||
static const int nproc_sysvipc_targets =
|
||||
sizeof(proc_sysvipc_targets) / sizeof(proc_sysvipc_targets[0]);
|
||||
|
||||
int procfs_lookup(void *);
|
||||
int procfs_open(void *);
|
||||
int procfs_close(void *);
|
||||
|
@ -723,10 +740,18 @@ procfs_getattr(void *v)
|
|||
case PFSself:
|
||||
case PFScurproc:
|
||||
case PFSroot:
|
||||
case PFSsysvipc_msg:
|
||||
case PFSsysvipc_sem:
|
||||
case PFSsysvipc_shm:
|
||||
vap->va_nlink = 1;
|
||||
vap->va_uid = vap->va_gid = 0;
|
||||
break;
|
||||
|
||||
case PFSsysvipc:
|
||||
vap->va_nlink = 5;
|
||||
vap->va_uid = vap->va_gid = 0;
|
||||
break;
|
||||
|
||||
case PFSproc:
|
||||
case PFStask:
|
||||
case PFSfile:
|
||||
|
@ -841,6 +866,10 @@ procfs_getattr(void *v)
|
|||
case PFSloadavg:
|
||||
case PFSstatm:
|
||||
case PFSversion:
|
||||
case PFSsysvipc:
|
||||
case PFSsysvipc_msg:
|
||||
case PFSsysvipc_sem:
|
||||
case PFSsysvipc_shm:
|
||||
vap->va_bytes = vap->va_size = 0;
|
||||
break;
|
||||
case PFSlimit:
|
||||
|
@ -1156,6 +1185,34 @@ procfs_lookup(void *v)
|
|||
procfs_proc_unlock(p);
|
||||
return error;
|
||||
}
|
||||
case PFSsysvipc:
|
||||
if (cnp->cn_flags & ISDOTDOT) {
|
||||
error = procfs_allocvp(dvp->v_mount, vpp, 0, PFSroot,
|
||||
-1);
|
||||
return (error);
|
||||
}
|
||||
|
||||
for (i = 0; i < nproc_sysvipc_targets; i++) {
|
||||
pt = &proc_sysvipc_targets[i];
|
||||
/*
|
||||
* check for node match. proc is always NULL here,
|
||||
* so call pt_valid with constant NULL lwp.
|
||||
*/
|
||||
if (cnp->cn_namelen == pt->pt_namlen &&
|
||||
memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
|
||||
(pt->pt_valid == NULL ||
|
||||
(*pt->pt_valid)(NULL, dvp->v_mount)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != nproc_sysvipc_targets) {
|
||||
error = procfs_allocvp(dvp->v_mount, vpp, 0,
|
||||
pt->pt_pfstype, -1);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
|
||||
default:
|
||||
return (ENOTDIR);
|
||||
}
|
||||
|
@ -1441,6 +1498,40 @@ procfs_readdir(void *v)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysvipc subdirectory
|
||||
*/
|
||||
case PFSsysvipc: {
|
||||
if ((error = procfs_proc_lock(vp->v_mount, pfs->pfs_pid, &p,
|
||||
ESRCH)) != 0)
|
||||
return error;
|
||||
if (ap->a_ncookies) {
|
||||
ncookies = uimin(ncookies, (nproc_sysvipc_targets - i));
|
||||
cookies = malloc(ncookies * sizeof (off_t),
|
||||
M_TEMP, M_WAITOK);
|
||||
*ap->a_cookies = cookies;
|
||||
}
|
||||
|
||||
for (pt = &proc_sysvipc_targets[i];
|
||||
uio->uio_resid >= UIO_MX && i < nproc_sysvipc_targets; pt++, i++) {
|
||||
if (pt->pt_valid &&
|
||||
(*pt->pt_valid)(NULL, vp->v_mount) == 0)
|
||||
continue;
|
||||
d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
|
||||
pt->pt_pfstype, -1);
|
||||
d.d_namlen = pt->pt_namlen;
|
||||
memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
|
||||
d.d_type = pt->pt_type;
|
||||
|
||||
if ((error = uiomove(&d, UIO_MX, uio)) != 0)
|
||||
break;
|
||||
if (cookies)
|
||||
*cookies++ = i + 1;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is for the root of the procfs filesystem
|
||||
* what is needed are special entries for "curproc"
|
||||
|
|
Loading…
Reference in New Issue