Module Name:    src
Committed By:   christos
Date:           Sun May 12 17:26:51 UTC 2024

Modified Files:
        src/sys/miscfs/procfs: procfs.h procfs_linux.c procfs_subr.c
            procfs_vfsops.c procfs_vnops.c

Log Message:
PR/58227: Ricardo Branco: Add support for proc/sysvipc in Linux emulator


To generate a diff of this commit:
cvs rdiff -u -r1.85 -r1.86 src/sys/miscfs/procfs/procfs.h
cvs rdiff -u -r1.87 -r1.88 src/sys/miscfs/procfs/procfs_linux.c
cvs rdiff -u -r1.118 -r1.119 src/sys/miscfs/procfs/procfs_subr.c
cvs rdiff -u -r1.115 -r1.116 src/sys/miscfs/procfs/procfs_vfsops.c
cvs rdiff -u -r1.231 -r1.232 src/sys/miscfs/procfs/procfs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/miscfs/procfs/procfs.h
diff -u src/sys/miscfs/procfs/procfs.h:1.85 src/sys/miscfs/procfs/procfs.h:1.86
--- src/sys/miscfs/procfs/procfs.h:1.85	Sun May 12 13:22:29 2024
+++ src/sys/miscfs/procfs/procfs.h	Sun May 12 13:26:50 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs.h,v 1.85 2024/05/12 17:22:29 christos Exp $	*/
+/*	$NetBSD: procfs.h,v 1.86 2024/05/12 17:26:50 christos Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -112,7 +112,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
@@ -272,6 +276,12 @@ int procfs_dolimit(struct lwp *, struct 
     struct uio *);
 int procfs_dolimits(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 **);

Index: src/sys/miscfs/procfs/procfs_linux.c
diff -u src/sys/miscfs/procfs/procfs_linux.c:1.87 src/sys/miscfs/procfs/procfs_linux.c:1.88
--- src/sys/miscfs/procfs/procfs_linux.c:1.87	Sat Sep  5 12:30:12 2020
+++ src/sys/miscfs/procfs/procfs_linux.c	Sun May 12 13:26:50 2024
@@ -1,4 +1,4 @@
-/*      $NetBSD: procfs_linux.c,v 1.87 2020/09/05 16:30:12 riastradh Exp $      */
+/*      $NetBSD: procfs_linux.c,v 1.88 2024/05/12 17:26:50 christos Exp $      */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.87 2020/09/05 16:30:12 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.88 2024/05/12 17:26:50 christos Exp $");
+
+#if defined(_KERNEL_OPT)
+#include "opt_sysv.h"
+#endif
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -58,6 +62,15 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_linux
 #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;
+}

Index: src/sys/miscfs/procfs/procfs_subr.c
diff -u src/sys/miscfs/procfs/procfs_subr.c:1.118 src/sys/miscfs/procfs/procfs_subr.c:1.119
--- src/sys/miscfs/procfs/procfs_subr.c:1.118	Sun May 12 13:22:29 2024
+++ src/sys/miscfs/procfs/procfs_subr.c	Sun May 12 13:26:50 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_subr.c,v 1.118 2024/05/12 17:22:29 christos Exp $	*/
+/*	$NetBSD: procfs_subr.c,v 1.119 2024/05/12 17:26:50 christos Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.118 2024/05/12 17:22:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.119 2024/05/12 17:26:50 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -287,6 +287,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);

Index: src/sys/miscfs/procfs/procfs_vfsops.c
diff -u src/sys/miscfs/procfs/procfs_vfsops.c:1.115 src/sys/miscfs/procfs/procfs_vfsops.c:1.116
--- src/sys/miscfs/procfs/procfs_vfsops.c:1.115	Sun May 12 13:22:29 2024
+++ src/sys/miscfs/procfs/procfs_vfsops.c	Sun May 12 13:26:50 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vfsops.c,v 1.115 2024/05/12 17:22:29 christos Exp $	*/
+/*	$NetBSD: procfs_vfsops.c,v 1.116 2024/05/12 17:26:50 christos Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.115 2024/05/12 17:22:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.116 2024/05/12 17:26:50 christos Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -437,6 +437,21 @@ procfs_loadvnode(struct mount *mp, struc
 		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);

Index: src/sys/miscfs/procfs/procfs_vnops.c
diff -u src/sys/miscfs/procfs/procfs_vnops.c:1.231 src/sys/miscfs/procfs/procfs_vnops.c:1.232
--- src/sys/miscfs/procfs/procfs_vnops.c:1.231	Sun May 12 13:22:29 2024
+++ src/sys/miscfs/procfs/procfs_vnops.c	Sun May 12 13:26:51 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vnops.c,v 1.231 2024/05/12 17:22:29 christos Exp $	*/
+/*	$NetBSD: procfs_vnops.c,v 1.232 2024/05/12 17:26:51 christos Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -105,7 +105,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.231 2024/05/12 17:22:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.232 2024/05/12 17:26:51 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -203,11 +203,28 @@ static const struct proc_target proc_roo
 	{ 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 *);
@@ -725,10 +742,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:
@@ -843,6 +868,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:
@@ -1159,6 +1188,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);
 	}
@@ -1445,6 +1502,40 @@ procfs_readdir(void *v)
 	}
 
 	/*
+	 * 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"
 	 * and "self" followed by an entry for each process

Reply via email to