summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_shm.c90
-rw-r--r--sys/security/mac/mac_framework.h4
-rw-r--r--sys/security/mac/mac_policy.h8
-rw-r--r--sys/security/mac/mac_posix_shm.c34
-rw-r--r--sys/security/mac_biba/mac_biba.c38
-rw-r--r--sys/security/mac_mls/mac_mls.c38
-rw-r--r--sys/security/mac_stub/mac_stub.c18
-rw-r--r--sys/security/mac_test/mac_test.c32
-rw-r--r--sys/sys/mman.h7
9 files changed, 266 insertions, 3 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 55f350a..d034071 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/time.h>
#include <sys/vnode.h>
+#include <sys/unistd.h>
#include <security/mac/mac_framework.h>
@@ -119,6 +120,7 @@ static fo_stat_t shm_stat;
static fo_close_t shm_close;
static fo_chmod_t shm_chmod;
static fo_chown_t shm_chown;
+static fo_seek_t shm_seek;
/* File descriptor operations. */
static struct fileops shm_ops = {
@@ -133,7 +135,8 @@ static struct fileops shm_ops = {
.fo_chmod = shm_chmod,
.fo_chown = shm_chown,
.fo_sendfile = invfo_sendfile,
- .fo_flags = DFLAG_PASSABLE
+ .fo_seek = shm_seek,
+ .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
FEATURE(posix_shm, "POSIX shared memory");
@@ -233,19 +236,96 @@ uiomove_object(vm_object_t obj, off_t obj_size, struct uio *uio)
}
static int
+shm_seek(struct file *fp, off_t offset, int whence, struct thread *td)
+{
+ struct shmfd *shmfd;
+ off_t foffset;
+ int error;
+
+ shmfd = fp->f_data;
+ foffset = foffset_lock(fp, 0);
+ error = 0;
+ switch (whence) {
+ case L_INCR:
+ if (foffset < 0 ||
+ (offset > 0 && foffset > OFF_MAX - offset)) {
+ error = EOVERFLOW;
+ break;
+ }
+ offset += foffset;
+ break;
+ case L_XTND:
+ if (offset > 0 && shmfd->shm_size > OFF_MAX - offset) {
+ error = EOVERFLOW;
+ break;
+ }
+ offset += shmfd->shm_size;
+ break;
+ case L_SET:
+ break;
+ default:
+ error = EINVAL;
+ }
+ if (error == 0) {
+ if (offset < 0 || offset > shmfd->shm_size)
+ error = EINVAL;
+ else
+ *(off_t *)(td->td_retval) = offset;
+ }
+ foffset_unlock(fp, offset, error != 0 ? FOF_NOUPDATE : 0);
+ return (error);
+}
+
+static int
shm_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
int flags, struct thread *td)
{
+ struct shmfd *shmfd;
+ void *rl_cookie;
+ int error;
- return (EOPNOTSUPP);
+ shmfd = fp->f_data;
+ foffset_lock_uio(fp, uio, flags);
+ rl_cookie = rangelock_rlock(&shmfd->shm_rl, uio->uio_offset,
+ uio->uio_offset + uio->uio_resid, &shmfd->shm_mtx);
+#ifdef MAC
+ error = mac_posixshm_check_read(active_cred, fp->f_cred, shmfd);
+ if (error)
+ return (error);
+#endif
+ error = uiomove_object(shmfd->shm_object, shmfd->shm_size, uio);
+ rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
+ foffset_unlock_uio(fp, uio, flags);
+ return (error);
}
static int
shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
int flags, struct thread *td)
{
+ struct shmfd *shmfd;
+ void *rl_cookie;
+ int error;
- return (EOPNOTSUPP);
+ shmfd = fp->f_data;
+#ifdef MAC
+ error = mac_posixshm_check_write(active_cred, fp->f_cred, shmfd);
+ if (error)
+ return (error);
+#endif
+ foffset_lock_uio(fp, uio, flags);
+ if ((flags & FOF_OFFSET) == 0) {
+ rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX,
+ &shmfd->shm_mtx);
+ } else {
+ rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset,
+ uio->uio_offset + uio->uio_resid, &shmfd->shm_mtx);
+ }
+
+ error = uiomove_object(shmfd->shm_object, shmfd->shm_size, uio);
+ rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
+ foffset_unlock_uio(fp, uio, flags);
+ return (error);
}
static int
@@ -471,6 +551,8 @@ shm_alloc(struct ucred *ucred, mode_t mode)
shmfd->shm_atime = shmfd->shm_mtime = shmfd->shm_ctime =
shmfd->shm_birthtime;
refcount_init(&shmfd->shm_refs, 1);
+ mtx_init(&shmfd->shm_mtx, "shmrl", NULL, MTX_DEF);
+ rangelock_init(&shmfd->shm_rl);
#ifdef MAC
mac_posixshm_init(shmfd);
mac_posixshm_create(ucred, shmfd);
@@ -495,6 +577,8 @@ shm_drop(struct shmfd *shmfd)
#ifdef MAC
mac_posixshm_destroy(shmfd);
#endif
+ rangelock_destroy(&shmfd->shm_rl);
+ mtx_destroy(&shmfd->shm_mtx);
vm_object_deallocate(shmfd->shm_object);
free(shmfd, M_SHMFD);
}
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index 92aedea..77cb8bc 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -243,6 +243,8 @@ int mac_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
int prot, int flags);
int mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
accmode_t accmode);
+int mac_posixshm_check_read(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd);
int mac_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
mode_t mode);
int mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
@@ -252,6 +254,8 @@ int mac_posixshm_check_stat(struct ucred *active_cred,
int mac_posixshm_check_truncate(struct ucred *active_cred,
struct ucred *file_cred, struct shmfd *shmfd);
int mac_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd);
+int mac_posixshm_check_write(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd);
void mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd);
void mac_posixshm_destroy(struct shmfd *);
void mac_posixshm_init(struct shmfd *);
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index 090dc40..dadadb5 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -363,6 +363,9 @@ typedef int (*mpo_posixshm_check_mmap_t)(struct ucred *cred,
typedef int (*mpo_posixshm_check_open_t)(struct ucred *cred,
struct shmfd *shmfd, struct label *shmlabel,
accmode_t accmode);
+typedef int (*mpo_posixshm_check_read_t)(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd,
+ struct label *shmlabel);
typedef int (*mpo_posixshm_check_setmode_t)(struct ucred *cred,
struct shmfd *shmfd, struct label *shmlabel,
mode_t mode);
@@ -377,6 +380,9 @@ typedef int (*mpo_posixshm_check_truncate_t)(struct ucred *active_cred,
struct label *shmlabel);
typedef int (*mpo_posixshm_check_unlink_t)(struct ucred *cred,
struct shmfd *shmfd, struct label *shmlabel);
+typedef int (*mpo_posixshm_check_write_t)(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd,
+ struct label *shmlabel);
typedef void (*mpo_posixshm_create_t)(struct ucred *cred,
struct shmfd *shmfd, struct label *shmlabel);
typedef void (*mpo_posixshm_destroy_label_t)(struct label *label);
@@ -818,11 +824,13 @@ struct mac_policy_ops {
mpo_posixshm_check_create_t mpo_posixshm_check_create;
mpo_posixshm_check_mmap_t mpo_posixshm_check_mmap;
mpo_posixshm_check_open_t mpo_posixshm_check_open;
+ mpo_posixshm_check_read_t mpo_posixshm_check_read;
mpo_posixshm_check_setmode_t mpo_posixshm_check_setmode;
mpo_posixshm_check_setowner_t mpo_posixshm_check_setowner;
mpo_posixshm_check_stat_t mpo_posixshm_check_stat;
mpo_posixshm_check_truncate_t mpo_posixshm_check_truncate;
mpo_posixshm_check_unlink_t mpo_posixshm_check_unlink;
+ mpo_posixshm_check_write_t mpo_posixshm_check_write;
mpo_posixshm_create_t mpo_posixshm_create;
mpo_posixshm_destroy_label_t mpo_posixshm_destroy_label;
mpo_posixshm_init_label_t mpo_posixshm_init_label;
diff --git a/sys/security/mac/mac_posix_shm.c b/sys/security/mac/mac_posix_shm.c
index d5d15fc..1202d46 100644
--- a/sys/security/mac/mac_posix_shm.c
+++ b/sys/security/mac/mac_posix_shm.c
@@ -228,3 +228,37 @@ mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd, uid_t uid,
return (error);
}
+
+MAC_CHECK_PROBE_DEFINE3(posixshm_check_read, "struct ucred *",
+ "struct ucred *", "struct shmfd *");
+
+int
+mac_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shmfd)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixshm_check_read, active_cred,
+ file_cred, shmfd, shmfd->shm_label);
+ MAC_CHECK_PROBE3(posixshm_check_read, error, active_cred,
+ file_cred, shmfd);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE3(posixshm_check_write, "struct ucred *",
+ "struct ucred *", "struct shmfd *");
+
+int
+mac_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shmfd)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixshm_check_write, active_cred,
+ file_cred, shmfd, shmfd->shm_label);
+ MAC_CHECK_PROBE3(posixshm_check_write, error, active_cred,
+ file_cred, shmfd);
+
+ return (error);
+}
diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c
index aa37fc7..4216fea 100644
--- a/sys/security/mac_biba/mac_biba.c
+++ b/sys/security/mac_biba/mac_biba.c
@@ -1759,6 +1759,24 @@ biba_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
}
static int
+biba_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *vp, struct label *shmlabel)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled || !revocation_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
biba_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel, mode_t mode)
{
@@ -1848,6 +1866,24 @@ biba_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+static int
+biba_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *vp, struct label *shmlabel)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled || !revocation_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
static void
biba_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel)
@@ -3657,11 +3693,13 @@ static struct mac_policy_ops mac_biba_ops =
.mpo_posixshm_check_mmap = biba_posixshm_check_mmap,
.mpo_posixshm_check_open = biba_posixshm_check_open,
+ .mpo_posixshm_check_read = biba_posixshm_check_read,
.mpo_posixshm_check_setmode = biba_posixshm_check_setmode,
.mpo_posixshm_check_setowner = biba_posixshm_check_setowner,
.mpo_posixshm_check_stat = biba_posixshm_check_stat,
.mpo_posixshm_check_truncate = biba_posixshm_check_truncate,
.mpo_posixshm_check_unlink = biba_posixshm_check_unlink,
+ .mpo_posixshm_check_write = biba_posixshm_check_write,
.mpo_posixshm_create = biba_posixshm_create,
.mpo_posixshm_destroy_label = biba_destroy_label,
.mpo_posixshm_init_label = biba_init_label,
diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c
index ff9084e..8980f50 100644
--- a/sys/security/mac_mls/mac_mls.c
+++ b/sys/security/mac_mls/mac_mls.c
@@ -1651,6 +1651,24 @@ mls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
}
static int
+mls_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shm, struct label *shmlabel)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled || !revocation_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
mls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel, mode_t mode)
{
@@ -1740,6 +1758,24 @@ mls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+static int
+mls_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shm, struct label *shmlabel)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled || !revocation_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
static void
mls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel)
@@ -3280,11 +3316,13 @@ static struct mac_policy_ops mls_ops =
.mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
.mpo_posixshm_check_open = mls_posixshm_check_open,
+ .mpo_posixshm_check_read = mls_posixshm_check_read,
.mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
.mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
.mpo_posixshm_check_stat = mls_posixshm_check_stat,
.mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
.mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
+ .mpo_posixshm_check_write = mls_posixshm_check_write,
.mpo_posixshm_create = mls_posixshm_create,
.mpo_posixshm_destroy_label = mls_destroy_label,
.mpo_posixshm_init_label = mls_init_label,
diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
index ed25d23..54a6753 100644
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -757,6 +757,14 @@ stub_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
}
static int
+stub_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shm, struct label *shmlabel)
+{
+
+ return (0);
+}
+
+static int
stub_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel, mode_t mode)
{
@@ -796,6 +804,14 @@ stub_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+static int
+stub_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shm, struct label *shmlabel)
+{
+
+ return (0);
+}
+
static void
stub_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel)
@@ -1782,11 +1798,13 @@ static struct mac_policy_ops stub_ops =
.mpo_posixshm_check_create = stub_posixshm_check_create,
.mpo_posixshm_check_mmap = stub_posixshm_check_mmap,
.mpo_posixshm_check_open = stub_posixshm_check_open,
+ .mpo_posixshm_check_read = stub_posixshm_check_read,
.mpo_posixshm_check_setmode = stub_posixshm_check_setmode,
.mpo_posixshm_check_setowner = stub_posixshm_check_setowner,
.mpo_posixshm_check_stat = stub_posixshm_check_stat,
.mpo_posixshm_check_truncate = stub_posixshm_check_truncate,
.mpo_posixshm_check_unlink = stub_posixshm_check_unlink,
+ .mpo_posixshm_check_write = stub_posixshm_check_write,
.mpo_posixshm_create = stub_posixshm_create,
.mpo_posixshm_destroy_label = stub_destroy_label,
.mpo_posixshm_init_label = stub_init_label,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
index 1781798..4d48dfd 100644
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -1423,6 +1423,21 @@ test_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+COUNTER_DECL(posixshm_check_read);
+static int
+test_posixshm_check_read(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shm, struct label *shmlabel)
+{
+
+ LABEL_CHECK(active_cred->cr_label, MAGIC_CRED);
+ if (file_cred != NULL)
+ LABEL_CHECK(file_cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(shmlabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixshm_check_read);
+
+ return (0);
+}
+
COUNTER_DECL(posixshm_check_setmode);
static int
test_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
@@ -1485,6 +1500,21 @@ test_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+COUNTER_DECL(posixshm_check_write);
+static int
+test_posixshm_check_write(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shm, struct label *shmlabel)
+{
+
+ LABEL_CHECK(active_cred->cr_label, MAGIC_CRED);
+ if (file_cred != NULL)
+ LABEL_CHECK(file_cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(shmlabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixshm_check_write);
+
+ return (0);
+}
+
COUNTER_DECL(posixshm_create);
static void
test_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
@@ -3114,11 +3144,13 @@ static struct mac_policy_ops test_ops =
.mpo_posixshm_check_create = test_posixshm_check_create,
.mpo_posixshm_check_mmap = test_posixshm_check_mmap,
.mpo_posixshm_check_open = test_posixshm_check_open,
+ .mpo_posixshm_check_read = test_posixshm_check_read,
.mpo_posixshm_check_setmode = test_posixshm_check_setmode,
.mpo_posixshm_check_setowner = test_posixshm_check_setowner,
.mpo_posixshm_check_stat = test_posixshm_check_stat,
.mpo_posixshm_check_truncate = test_posixshm_check_truncate,
.mpo_posixshm_check_unlink = test_posixshm_check_unlink,
+ .mpo_posixshm_check_write = test_posixshm_check_write,
.mpo_posixshm_create = test_posixshm_create,
.mpo_posixshm_destroy_label = test_posixshm_destroy_label,
.mpo_posixshm_init_label = test_posixshm_init_label,
diff --git a/sys/sys/mman.h b/sys/sys/mman.h
index c5e47a0..32f0e7b 100644
--- a/sys/sys/mman.h
+++ b/sys/sys/mman.h
@@ -190,6 +190,10 @@ typedef __size_t size_t;
#endif
#if defined(_KERNEL) || defined(_WANT_FILE)
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/rangelock.h>
#include <vm/vm.h>
struct file;
@@ -214,6 +218,9 @@ struct shmfd {
struct label *shm_label; /* MAC label */
const char *shm_path;
+
+ struct rangelock shm_rl;
+ struct mtx shm_mtx;
};
#endif
OpenPOWER on IntegriCloud