procfs: Support sysvipc/{msg,sem,shm} used by linux

pull/36/head
Ricardo Branco 2024-05-05 19:11:40 +02:00
parent b129f29edd
commit 02571cb3a8
No known key found for this signature in database
5 changed files with 280 additions and 1 deletions

View File

@ -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 **);

View 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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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"