From e656d3b0f67ff865d95b4ddb842cc19f893475e6 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Sun, 4 Sep 2011 17:32:10 +0000 Subject: [PATCH] PR# kern/45021: Please support /emul/linux/proc/version Add /proc/version for procfs with -o linux. The version reported depends on the emulation type of the calling process: $ cat /proc/version NetBSD version 5.99.55 (netbsd@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) NetBSD 5.99.55 (GENERIC) #39: Sun Sep 4 09:10:05 EDT 2011 $ /emul/linux/bin/cat /proc/version Linux version 2.6.18 (linux@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) #0 Wed Mar 3 03:03:03 PST 2010 $ /emul/linux32/bin/cat /proc/version Linux version 2.6.18 (linux32@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) #0 Wed Mar 3 03:03:03 PST 2010 --- sys/miscfs/procfs/procfs.h | 5 +- sys/miscfs/procfs/procfs_linux.c | 105 ++++++++++++++++++++++++++++++- sys/miscfs/procfs/procfs_subr.c | 9 ++- sys/miscfs/procfs/procfs_vnops.c | 7 ++- 4 files changed, 119 insertions(+), 7 deletions(-) diff --git a/sys/miscfs/procfs/procfs.h b/sys/miscfs/procfs/procfs.h index 10914be9e363..a08e0b7fc808 100644 --- a/sys/miscfs/procfs/procfs.h +++ b/sys/miscfs/procfs/procfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: procfs.h,v 1.65 2008/06/28 01:34:06 rumble Exp $ */ +/* $NetBSD: procfs.h,v 1.66 2011/09/04 17:32:10 jmcneill Exp $ */ /* * Copyright (c) 1993 @@ -108,6 +108,7 @@ typedef enum { PFScpustat, /* status info (if -o linux) */ PFSloadavg, /* load average (if -o linux) */ PFSstatm, /* process memory info (if -o linux) */ + PFSversion, /* kernel version (if -o linux) */ #ifdef __HAVE_PROCFS_MACHDEP PROCFS_MACHDEP_NODE_TYPES #endif @@ -225,6 +226,8 @@ int procfs_domounts(struct lwp *, struct proc *, struct pfsnode *, struct uio *); int procfs_doemul(struct lwp *, struct proc *, struct pfsnode *, struct uio *); +int procfs_doversion(struct lwp *, struct proc *, struct pfsnode *, + struct uio *); void procfs_revoke_vnodes(struct proc *, void *); void procfs_hashinit(void); diff --git a/sys/miscfs/procfs/procfs_linux.c b/sys/miscfs/procfs/procfs_linux.c index 2814e6d9171d..03fe3e7aefb9 100644 --- a/sys/miscfs/procfs/procfs_linux.c +++ b/sys/miscfs/procfs/procfs_linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill Exp $ */ +/* $NetBSD: procfs_linux.c,v 1.61 2011/09/04 17:32:10 jmcneill Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.61 2011/09/04 17:32:10 jmcneill Exp $"); #include #include @@ -53,10 +53,12 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill E #include #include #include +#include #include #include +#include #include #include @@ -610,3 +612,102 @@ procfs_domounts(struct lwp *curl, struct proc *p, return error; } + +/* + * Linux compatible /proc/version. Only active when the -o linux + * mountflag is used. + */ +int +procfs_doversion(struct lwp *curl, struct proc *p, + struct pfsnode *pfs, struct uio *uio) +{ + char *bf; + char lostype[20], losrelease[20], lversion[80]; + const char *postype, *posrelease, *pversion; + const char *emulname = curlwp->l_proc->p_emul->e_name; + int len; + int error = 0; + int nm[4]; + size_t buflen; + + CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE); + CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE); + CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION); + + bf = malloc(LBFSZ, M_TEMP, M_WAITOK); + + sysctl_lock(false); + + if (strncmp(emulname, "linux", 5) == 0) { + /* + * Lookup the emulation ostype, osrelease, and version. + * Since compat_linux and compat_linux32 can be built as + * modules, we use sysctl to obtain the values instead of + * using the symbols directly. + */ + + if (strcmp(emulname, "linux32") == 0) { + nm[0] = CTL_EMUL; + nm[1] = EMUL_LINUX32; + nm[2] = EMUL_LINUX32_KERN; + } else { + nm[0] = CTL_EMUL; + nm[1] = EMUL_LINUX; + nm[2] = EMUL_LINUX_KERN; + } + + nm[3] = EMUL_LINUX_KERN_OSTYPE; + buflen = sizeof(lostype); + error = sysctl_dispatch(nm, __arraycount(nm), + lostype, &buflen, + NULL, 0, NULL, NULL, NULL); + if (error) + goto out; + + nm[3] = EMUL_LINUX_KERN_OSRELEASE; + buflen = sizeof(losrelease); + error = sysctl_dispatch(nm, __arraycount(nm), + losrelease, &buflen, + NULL, 0, NULL, NULL, NULL); + if (error) + goto out; + + nm[3] = EMUL_LINUX_KERN_VERSION; + buflen = sizeof(lversion); + error = sysctl_dispatch(nm, __arraycount(nm), + lversion, &buflen, + NULL, 0, NULL, NULL, NULL); + if (error) + goto out; + + postype = lostype; + posrelease = losrelease; + pversion = lversion; + } else { + postype = ostype; + posrelease = osrelease; + strlcpy(lversion, version, sizeof(lversion)); + if (strchr(lversion, '\n')) + *strchr(lversion, '\n') = '\0'; + pversion = lversion; + } + + len = snprintf(bf, LBFSZ, + "%s version %s (%s@localhost) (gcc version %s) %s\n", + postype, posrelease, emulname, +#ifdef __VERSION__ + __VERSION__, +#else + "unknown", +#endif + pversion); + + if (len == 0) + goto out; + + error = uiomove_frombuf(bf, len, uio); +out: + free(bf, M_TEMP); + sysctl_unlock(); + return error; +} diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c index 8881d0d5581e..9016b8e5c491 100644 --- a/sys/miscfs/procfs/procfs_subr.c +++ b/sys/miscfs/procfs/procfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_subr.c,v 1.99 2011/06/12 03:35:58 rmind Exp $ */ +/* $NetBSD: procfs_subr.c,v 1.100 2011/09/04 17:32:10 jmcneill Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -102,7 +102,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.99 2011/06/12 03:35:58 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.100 2011/09/04 17:32:10 jmcneill Exp $"); #include #include @@ -288,6 +288,7 @@ procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, case PFSmounts: /* /proc/mounts = -r--r--r-- */ case PFSloadavg: /* /proc/loadavg = -r--r--r-- */ case PFSstatm: /* /proc/N/statm = -r--r--r-- */ + case PFSversion: /* /proc/version = -r--r--r-- */ pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; vp->v_type = VREG; break; @@ -462,6 +463,10 @@ procfs_rw(void *v) error = procfs_doemul(curl, p, pfs, uio); break; + case PFSversion: + error = procfs_doversion(curl, p, pfs, uio); + break; + #ifdef __HAVE_PROCFS_MACHDEP PROCFS_MACHDEP_NODETYPE_CASES error = procfs_machdep_rw(curl, l, pfs, uio); diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c index 408027444ce8..0e1f2e1f7d16 100644 --- a/sys/miscfs/procfs/procfs_vnops.c +++ b/sys/miscfs/procfs/procfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_vnops.c,v 1.181 2011/06/23 17:06:38 christos Exp $ */ +/* $NetBSD: procfs_vnops.c,v 1.182 2011/09/04 17:32:10 jmcneill Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -105,7 +105,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.181 2011/06/23 17:06:38 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.182 2011/09/04 17:32:10 jmcneill Exp $"); #include #include @@ -196,6 +196,7 @@ static const struct proc_target proc_root_targets[] = { { DT_REG, N("devices"), PFSdevices, procfs_validfile_linux }, { DT_REG, N("stat"), PFScpustat, procfs_validfile_linux }, { DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux }, + { DT_REG, N("version"), PFSversion, procfs_validfile_linux }, #undef N }; static const int nproc_root_targets = @@ -736,6 +737,7 @@ procfs_getattr(void *v) case PFSmounts: case PFScpustat: case PFSloadavg: + case PFSversion: vap->va_nlink = 1; vap->va_uid = vap->va_gid = 0; break; @@ -845,6 +847,7 @@ procfs_getattr(void *v) case PFScpustat: case PFSloadavg: case PFSstatm: + case PFSversion: vap->va_bytes = vap->va_size = 0; break; case PFSmap: