Add a kern.ipc.posix_shm_list sysctl.
The sysctl provides the listing on named linked posix shared memory segments existing in the system. Reuse shm_fill_kinfo() for filling individual struct kinfo_file. Remove unneeded lock around reading of shmfd->shm_mode. Reviewed by: jilles, tmunro Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D20258
This commit is contained in:
parent
b45119a2cb
commit
83a359ea2a
@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -1101,34 +1102,89 @@ shm_unmap(struct file *fp, void *mem, size_t size)
|
||||
}
|
||||
|
||||
static int
|
||||
shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
|
||||
shm_fill_kinfo_locked(struct shmfd *shmfd, struct kinfo_file *kif, bool list)
|
||||
{
|
||||
const char *path, *pr_path;
|
||||
struct shmfd *shmfd;
|
||||
size_t pr_pathlen;
|
||||
bool visible;
|
||||
|
||||
sx_assert(&shm_dict_lock, SA_LOCKED);
|
||||
kif->kf_type = KF_TYPE_SHM;
|
||||
shmfd = fp->f_data;
|
||||
|
||||
mtx_lock(&shm_timestamp_lock);
|
||||
kif->kf_un.kf_file.kf_file_mode = S_IFREG | shmfd->shm_mode; /* XXX */
|
||||
mtx_unlock(&shm_timestamp_lock);
|
||||
kif->kf_un.kf_file.kf_file_mode = S_IFREG | shmfd->shm_mode;
|
||||
kif->kf_un.kf_file.kf_file_size = shmfd->shm_size;
|
||||
if (shmfd->shm_path != NULL) {
|
||||
sx_slock(&shm_dict_lock);
|
||||
if (shmfd->shm_path != NULL) {
|
||||
path = shmfd->shm_path;
|
||||
pr_path = curthread->td_ucred->cr_prison->pr_path;
|
||||
if (strcmp(pr_path, "/") != 0) {
|
||||
/* Return the jail-rooted pathname. */
|
||||
pr_pathlen = strlen(pr_path);
|
||||
if (strncmp(path, pr_path, pr_pathlen) == 0 &&
|
||||
path[pr_pathlen] == '/')
|
||||
visible = strncmp(path, pr_path, pr_pathlen)
|
||||
== 0 && path[pr_pathlen] == '/';
|
||||
if (list && !visible)
|
||||
return (EPERM);
|
||||
if (visible)
|
||||
path += pr_pathlen;
|
||||
}
|
||||
strlcpy(kif->kf_path, path, sizeof(kif->kf_path));
|
||||
}
|
||||
sx_sunlock(&shm_dict_lock);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_fill_kinfo(struct file *fp, struct kinfo_file *kif,
|
||||
struct filedesc *fdp __unused)
|
||||
{
|
||||
int res;
|
||||
|
||||
sx_slock(&shm_dict_lock);
|
||||
res = shm_fill_kinfo_locked(fp->f_data, kif, false);
|
||||
sx_sunlock(&shm_dict_lock);
|
||||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct shm_mapping *shmm;
|
||||
struct sbuf sb;
|
||||
struct kinfo_file kif;
|
||||
u_long i;
|
||||
ssize_t curlen;
|
||||
int error, error2;
|
||||
|
||||
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file) * 5, req);
|
||||
sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
|
||||
curlen = 0;
|
||||
error = 0;
|
||||
sx_slock(&shm_dict_lock);
|
||||
for (i = 0; i < shm_hash + 1; i++) {
|
||||
LIST_FOREACH(shmm, &shm_dictionary[i], sm_link) {
|
||||
error = shm_fill_kinfo_locked(shmm->sm_shmfd,
|
||||
&kif, true);
|
||||
if (error == EPERM)
|
||||
continue;
|
||||
if (error != 0)
|
||||
break;
|
||||
pack_kinfo(&kif);
|
||||
if (req->oldptr != NULL &&
|
||||
kif.kf_structsize + curlen > req->oldlen)
|
||||
break;
|
||||
error = sbuf_bcat(&sb, &kif, kif.kf_structsize) == 0 ?
|
||||
0 : ENOMEM;
|
||||
if (error != 0)
|
||||
break;
|
||||
curlen += kif.kf_structsize;
|
||||
}
|
||||
}
|
||||
sx_sunlock(&shm_dict_lock);
|
||||
error2 = sbuf_finish(&sb);
|
||||
sbuf_delete(&sb);
|
||||
return (error != 0 ? error : error2);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_kern_ipc, OID_AUTO, posix_shm_list,
|
||||
CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_OPAQUE,
|
||||
NULL, 0, sysctl_posix_shm_list, "",
|
||||
"POSIX SHM list");
|
||||
|
Loading…
Reference in New Issue
Block a user