summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authordchagin <dchagin@FreeBSD.org>2016-01-09 17:27:36 +0000
committerdchagin <dchagin@FreeBSD.org>2016-01-09 17:27:36 +0000
commitd06d6422de7c5bb6015940e8cea11ea8a5faaa2c (patch)
tree8fa29b9cd06179399965d3a88c0982141900af57 /sys/compat
parenta25677a89beedfc42ad12b8cc9496a806f4e79db (diff)
downloadFreeBSD-src-d06d6422de7c5bb6015940e8cea11ea8a5faaa2c.zip
FreeBSD-src-d06d6422de7c5bb6015940e8cea11ea8a5faaa2c.tar.gz
MFC r283473:
Add support for /proc/<pid>/auxv.
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linprocfs/linprocfs.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 4944251..0c1ab66 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
+#include <sys/systm.h>
#include <sys/blist.h>
#include <sys/conf.h>
#include <sys/exec.h>
@@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/filedesc.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/limits.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -1364,6 +1366,52 @@ linprocfs_douuid(PFS_FILL_ARGS)
return(0);
}
+/*
+ * Filler function for proc/pid/auxv
+ */
+static int
+linprocfs_doauxv(PFS_FILL_ARGS)
+{
+ struct sbuf *asb;
+ off_t buflen, resid;
+ int error;
+
+ /*
+ * Mimic linux behavior and pass only processes with usermode
+ * address space as valid. Return zero silently otherwise.
+ */
+ if (p->p_vmspace == &vmspace0)
+ return (0);
+
+ if (uio->uio_resid == 0)
+ return (0);
+ if (uio->uio_offset < 0 || uio->uio_resid < 0)
+ return (EINVAL);
+
+ asb = sbuf_new_auto();
+ if (asb == NULL)
+ return (ENOMEM);
+ error = proc_getauxv(td, p, asb);
+ if (error == 0)
+ error = sbuf_finish(asb);
+
+ resid = sbuf_len(asb) - uio->uio_offset;
+ if (resid > uio->uio_resid)
+ buflen = uio->uio_resid;
+ else
+ buflen = resid;
+ if (buflen > IOSIZE_MAX)
+ return (EINVAL);
+ if (buflen > MAXPHYS)
+ buflen = MAXPHYS;
+ if (resid <= 0)
+ return (0);
+
+ if (error == 0)
+ error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
+ sbuf_delete(asb);
+ return (error);
+}
/*
* Constructor
@@ -1439,6 +1487,8 @@ linprocfs_init(PFS_INIT_ARGS)
NULL, NULL, NULL, PFS_RD);
pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "auxv", &linprocfs_doauxv,
+ NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
/* /proc/scsi/... */
dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
OpenPOWER on IntegriCloud