diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_socket.c | 447 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 5 | ||||
-rw-r--r-- | sys/kern/kern_uio.c | 156 | ||||
-rw-r--r-- | sys/kern/kern_vsr.c | 344 |
4 files changed, 952 insertions, 0 deletions
diff --git a/sys/kern/kern_socket.c b/sys/kern/kern_socket.c new file mode 100644 index 0000000..a6cc8d2 --- /dev/null +++ b/sys/kern/kern_socket.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/socket.h> +#include <sys/sio.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/filedesc.h> +#include <sys/vnode.h> +#include <vm/dynalloc.h> +#include <string.h> + +#define pr_trace(fmt, ...) kprintf("socket: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +static struct vops socket_vops; + +/* + * Get a kernel socket structure from a + * file descriptor. + * + * @sockfd: File descriptor to lookup + * @res: Result pointer + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +static int +get_ksock(int sockfd, struct ksocket **res) +{ + struct ksocket *ksock; + struct filedesc *fdesc; + struct vnode *vp; + + if (res == NULL) { + return -EINVAL; + } + + /* Grab the file descriptor */ + fdesc = fd_get(sockfd); + if (fdesc == NULL) { + return -EBADF; + } + + /* Is this even a socket? */ + if ((vp = fdesc->vp) == NULL) { + return -ENOTSOCK; + } + if (vp->type != VSOCK) { + return -ENOTSOCK; + } + + ksock = vp->data; + if (__unlikely(ksock == NULL)) { + return -EIO; + } + + *res = ksock; + return 0; +} + +/* + * VFS reclaim callback for the socket + * layer + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +static int +socket_reclaim(struct vnode *vp) +{ + struct ksocket *ksock; + + /* Is this even a socket? */ + if (vp->type != VSOCK) { + return -ENOTSOCK; + } + + /* Is there any data attached? */ + if ((ksock = vp->data) == NULL) { + return -EIO; + } + + fd_close(ksock->sockfd); + mutex_free(ksock->mtx); + dynfree(ksock); + return 0; +} + +/* + * Send data to socket - POSIX send(2) core + * + * @sockfd: File descriptor that backs this socket + * @buf: Buffer containing data to transmit + * @size: Size of the buffer + * @flags: Optional flags + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +ssize_t +send(int sockfd, const void *buf, size_t size, int flags) +{ + struct ksocket *ksock; + struct sockbuf *sbuf; + struct netbuf *netbuf; + size_t tail; + int error; + + /* Size cannot be zero */ + if (size == 0) { + return -EINVAL; + } + + if ((error = get_ksock(sockfd, &ksock)) < 0) { + return error; + } + + sbuf = &ksock->buf; + netbuf = &sbuf->buf; + mutex_acquire(ksock->mtx, 0); + + /* Make sure we dont overflow */ + if (netbuf->len > sbuf->watermark) { + mutex_release(ksock->mtx); + return -ENOBUFS; + } + + if (netbuf->len == 0) { + sbuf->head = 0; + sbuf->tail = 0; + } + + /* Clamp the size if needed */ + if ((netbuf->len + size) > sbuf->watermark) { + size = sbuf->watermark - netbuf->len; + } + if (size == 0) { + return -ENOBUFS; + } + + /* Copy the new data */ + tail = sbuf->tail; + memcpy(&netbuf->data[tail], buf, size); + + sbuf->tail += size; + netbuf->len += size; + mutex_release(ksock->mtx); + return size; +} + +/* + * Recv data from socket - POSIX recv(2) core + * + * @sockfd: File descriptor that backs this socket + * @buf: RX buffer + * @size: Size of the buffer + * @flags: Optional flags + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +ssize_t +recv(int sockfd, void *buf, size_t len, int flags) +{ + struct ksocket *ksock; + struct sockbuf *sbuf; + struct netbuf *netbuf; + size_t head; + int error; + + /* Length cannot be zero */ + if (len == 0) { + return -EINVAL; + } + + if ((error = get_ksock(sockfd, &ksock)) < 0) { + return error; + } + + sbuf = &ksock->buf; + netbuf = &sbuf->buf; + mutex_acquire(ksock->mtx, 0); + + /* Is it empty? */ + if (netbuf->len == 0) { + sbuf->head = 0; + sbuf->tail = 0; + return -EAGAIN; + } + + if (len > netbuf->len) { + len = netbuf->len; + } + + head = sbuf->head; + memcpy(buf, &netbuf->data[head], len); + + sbuf->head = (sbuf->head + len) % NETBUF_LEN; + mutex_release(ksock->mtx); + return len; +} + +/* + * POSIX socket(7) core + * + * @domain: Address family (see AF_*) + * @type: Socket type + * @protocol: Socket protocol + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +int +socket(int domain, int type, int protocol) +{ + struct vnode *vp = NULL; + struct ksocket *ksock = NULL; + struct filedesc *fdesc = NULL; + struct sockbuf *sbuf = NULL; + int fd, error = -1; + + if ((error = fd_alloc(&fdesc)) < 0) { + return error; + } + + fd = fdesc->fdno; + + /* Grab a new socket vnode */ + if ((error = vfs_alloc_vnode(&vp, VSOCK)) < 0) { + fd_close(fd); + return error; + } + + if (vp == NULL) { + error = -ENOBUFS; + goto fail; + } + + ksock = dynalloc(sizeof(*ksock)); + if (ksock == NULL) { + error = -ENOMEM; + goto fail; + } + + fdesc->vp = vp; + vp->vops = &socket_vops; + + sbuf = &ksock->buf; + sbuf->head = 0; + sbuf->tail = 0; + + switch (domain) { + case AF_UNIX: + { + struct sockaddr_un *un; + + un = &ksock->un; + sbuf->watermark = NETBUF_LEN; + + /* + * XXX: We could allow actual paths within the + * file system for sockets. + */ + un->sun_family = domain; + un->sun_path[0] = '\0'; + vp->data = ksock; + } + return fd; + default: + error = -EINVAL; + break; + } + +fail: + if (ksock != NULL) + dynfree(ksock); + if (vp != NULL) + vfs_release_vnode(vp); + + fd_close(fd); + return error; +} + +/* + * Bind address to socket - POSIX bind(2) core + * + * @sockfd: File descriptor + * @addr: Address to bind + * @len: Sockaddr len + * + * Returns zero on success, otherwise a less + * than zero errno. + */ +int +bind(int sockfd, const struct sockaddr *addr, socklen_t len) +{ + struct ksocket *ksock; + int error; + + if ((error = get_ksock(sockfd, &ksock)) < 0) { + kprintf("error=%d\n", error); + return error; + } + + /* Create the new mutex lock */ + ksock->mtx = mutex_new("ksocket"); + if (ksock->mtx == NULL) { + return -ENOMEM; + } + return 0; +} + +/* + * socket(7) syscall + * + * arg0: domain + * arg1: type + * arg2: protocol + */ +scret_t +sys_socket(struct syscall_args *scargs) +{ + int domain = scargs->arg0; + int type = scargs->arg1; + int protocol = scargs->arg2; + + return socket(domain, type, protocol); +} + +/* + * bind(2) syscall + * + * arg0: sockfd + * arg1: addr + * arg2: len + */ +scret_t +sys_bind(struct syscall_args *scargs) +{ + const struct sockaddr *u_addr = (void *)scargs->arg1; + struct sockaddr addr_copy; + int sockfd = scargs->arg0; + int len = scargs->arg2; + int error; + + error = copyin(u_addr, &addr_copy, sizeof(addr_copy)); + if (error < 0) { + return error; + } + + return bind(sockfd, &addr_copy, len); +} + +/* + * recv(2) syscall + * + * arg0: sockfd + * arg1: buf + * arg2: size + * arg3: flags + */ +scret_t +sys_recv(struct syscall_args *scargs) +{ + char buf[NETBUF_LEN]; + void *u_buf = (void *)scargs->arg1; + int sockfd = scargs->arg0; + size_t len = scargs->arg2; + int error, flags = scargs->arg3; + + if (len > sizeof(buf)) { + return -ENOBUFS; + } + + error = recv(sockfd, buf, len, flags); + if (error < 0) { + pr_error("sys_recv: recv() fail (fd=%d)\n", sockfd); + return error; + } + + error = copyout(buf, u_buf, len); + return (error == 0) ? len : error; +} + +/* + * send(2) syscall + * + * arg0: sockfd + * arg1: buf + * arg2: size + * arg3: flags + */ +scret_t +sys_send(struct syscall_args *scargs) +{ + char buf[NETBUF_LEN]; + const void *u_buf = (void *)scargs->arg1; + int sockfd = scargs->arg0; + size_t len = scargs->arg2; + int error, flags = scargs->arg3; + + if (len > sizeof(buf)) { + return -ENOBUFS; + } + + error = copyin(u_buf, buf, len); + if (error < 0) { + pr_error("sys_send: copyin() failure (fd=%d)\n", sockfd); + return error; + } + + return send(sockfd, buf, len, flags); +} + +static struct vops socket_vops = { + .read = NULL, + .write = NULL, + .reclaim = socket_reclaim, +}; diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index cb7e1d2..dd3de4f 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -29,6 +29,7 @@ #include <sys/syscall.h> #include <sys/sysctl.h> +#include <sys/socket.h> #include <sys/reboot.h> #include <sys/types.h> #include <sys/ucred.h> @@ -60,6 +61,10 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_setuid, /* SYS_setuid */ sys_getuid, /* SYS_getuid */ sys_waitpid, /* SYS_waitpid */ + sys_socket, /* SYS_socket */ + sys_bind, /* SYS_bind */ + sys_recv, /* SYS_recv */ + sys_send, /* SYS_send */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); diff --git a/sys/kern/kern_uio.c b/sys/kern/kern_uio.c new file mode 100644 index 0000000..dd533c2 --- /dev/null +++ b/sys/kern/kern_uio.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/limits.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/filedesc.h> + +/* + * Read data into POSIX.1‐2017 iovec + * + * @filedes: File descriptor number + * @iov: I/O vector to read file into + * @iovnt: Number of I/O vectors + */ +ssize_t +readv(int filedes, const struct iovec *iov, int iovcnt) +{ + void *base; + size_t len; + ssize_t tmp, bytes_read = 0; + + if (filedes < 0) { + return -EINVAL; + } + + /* + * Make sure that this conforms to our max + * iovec limit. + */ + if (iovcnt > IOVEC_MAX) { + return -EINVAL; + } + + /* + * Go through each I/O vector and read a chunk + * of data into one. + */ + for (int i = 0; i < iovcnt; ++i) { + base = iov[i].iov_base; + len = iov[i].iov_len; + + /* + * If we encounter a base that is NULL, + * or if the length to read is an invalid + * value of zero. We can just assume this + * is some sort of weird list termination? + */ + if (base == NULL || len == 0) { + break; + } + + /* Read the file into this base */ + tmp = fd_read(filedes, base, len); + + /* Did anything go wrong? */ + if (tmp < 0) { + return tmp; + } + + /* No more data */ + if (tmp == 0) { + break; + } + + /* Read more bytes */ + bytes_read += tmp; + } + + return bytes_read; +} + +/* + * Write data from POSIX.1‐2017 iovec + * + * @filedes: File descriptor number + * @iov: I/O vector to write to file + * @iovnt: Number of I/O vectors + */ +ssize_t +writev(int filedes, const struct iovec *iov, int iovcnt) +{ + void *base; + size_t len; + ssize_t bytes_written = 0; + ssize_t tmp; + + if (filedes < 0) { + return -EINVAL; + } + + /* + * Are we within the limits? Return an + * error if not. + */ + if (iovcnt > IOVEC_MAX) { + return -EINVAL; + } + + for (int i = 0; i < iovcnt; ++i) { + base = iov[i].iov_base; + len = iov[i].iov_len; + + /* + * These are invalid, whatever these are, + * terminate our walk through. + */ + if (base == NULL || len == 0) { + break; + } + + /* Write the data from the iovec */ + tmp = fd_write(filedes, base, len); + + /* Was there an error? */ + if (tmp < 0) { + return tmp; + } + + /* No more data to read? */ + if (tmp == 0) { + break; + } + + bytes_written += tmp; + } + + return bytes_written; +} diff --git a/sys/kern/kern_vsr.c b/sys/kern/kern_vsr.c new file mode 100644 index 0000000..c59be1e --- /dev/null +++ b/sys/kern/kern_vsr.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/vsr.h> +#include <sys/proc.h> +#include <sys/param.h> +#include <sys/limits.h> +#include <sys/syslog.h> +#include <vm/dynalloc.h> +#include <string.h> + +#define pr_trace(fmt, ...) kprintf("vsr: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +static uint32_t +fnv1_hash(const char *s) +{ + uint32_t hash = 2166136261UL; + const uint8_t *p = (uint8_t *)s; + + while (*p != '\0') { + hash ^= *p; + hash = hash * 0x01000193; + ++p; + } + + return hash; +} + +/* + * Add a VSR capsule to a domain. + */ +static void +vsr_domain_add(struct vsr_domain *vsp, struct vsr_capsule *cap) +{ + struct vsr_table *tab; + struct vsr_capsule **slot; + uint32_t hash; + + if (vsp == NULL || cap == NULL) { + return; + } + + if (cap->name == NULL) { + pr_error("vsr_domain_add: cap->name == NULL\n"); + return; + } + + tab = &vsp->table; + hash = fnv1_hash(cap->name); + slot = &tab->capsules[hash % VSR_MAX_CAPSULE]; + + /* If this slot is free, set it */ + if (*slot == NULL) { + *slot = cap; + return; + } + + /* Handle collision */ + TAILQ_INSERT_TAIL(&(*slot)->buckets, cap, link); +} + +/* + * Handle VSR domain hashmap collisions. + * + * @slot: Slot that we have collided with + * @name: Name to lookup + * + * Returns the pointer to the actual capsule if the + * collision has been resolved, otherwise, NULL if the + * entry to look up was not found. + */ +static struct vsr_capsule * +vsr_domain_clash(struct vsr_capsule *slot, const char *name) +{ + struct vsr_capsule *cap_ent; + + TAILQ_FOREACH(cap_ent, &slot->buckets, link) { + if (cap_ent == NULL) { + continue; + } + + if (strcmp(cap_ent->name, name) == 0) { + return cap_ent; + } + } + + return NULL; +} + +/* + * Lookup a capsule within a VSR domain + * by name. + * + * @vsp: Domain to lookup within + * @name: Name to use as lookup key + * + * Returns NULL if no entry was found. + */ +static struct vsr_capsule * +vfs_domain_lookup(struct vsr_domain *vsp, const char *name) +{ + uint32_t hash; + struct vsr_table *tab; + struct vsr_capsule **slot; + + if (vsp == NULL || name == NULL) { + return NULL; + } + + tab = &vsp->table; + hash = fnv1_hash(name); + slot = &tab->capsules[hash % VSR_MAX_CAPSULE]; + + if (*slot == NULL) { + return NULL; + } + + if (strcmp((*slot)->name, name) != 0) { + return vsr_domain_clash(*slot, name); + } + + return *slot; +} + +/* + * Destroy a VSR capsule + * + * @capule: Capsule to destroy + */ +static void +vsr_destroy_capsule(struct vsr_capsule *capsule) +{ + struct vsr_capsule *bucket; + struct capsule_ops *ops; + + if (capsule->name != NULL) { + dynfree(capsule->name); + capsule->name = NULL; + } + + ops = &capsule->ops; + if (ops->reclaim != NULL) { + ops->reclaim(capsule, 0); + } + + TAILQ_FOREACH(bucket, &capsule->buckets, link) { + if (bucket == NULL) { + continue; + } + vsr_destroy_capsule(bucket); + } + + /* Release any held locks */ + mutex_release(&capsule->lock); +} + +/* + * Destroy a VSR table + * + * @tab: Table to destroy. + */ +static void +vsr_destroy_table(struct vsr_table *tab) +{ + struct vsr_capsule *capsule; + + if (tab == NULL) { + pr_error("vsr_destroy_table: tab is NULL\n"); + return; + } + + for (int i = 0; i < VSR_MAX_CAPSULE; ++i) { + if ((capsule = tab->capsules[i]) == NULL) { + continue; + } + + vsr_destroy_capsule(capsule); + } +} + +/* + * Allocate a new VSR capsule and add it to + * VSR domain. + * + * @type: Domain type (e.g., VSR_FILE) + * @name: Capsule name (e.g., "mod0.data") + * @sz: Length of capsulized data + */ +struct vsr_capsule * +vsr_new_capsule(struct proc *td, vsr_domain_t type, const char *name) +{ + struct vsr_capsule *capsule; + struct vsr_domain *domain; + + /* Valid args? */ + if (type >= VSR_MAX_DOMAIN || td == NULL) { + return NULL; + } + + /* + * The VSR domain must be registered for + * us to add any capsules to it. + */ + if ((domain = td->vsr_tab[type]) == NULL) { + pr_error("VSR domain %d not registered\n", type); + return NULL; + } + + /* Allocate a new capsule */ + capsule = dynalloc(sizeof(*capsule)); + if (capsule == NULL) { + return NULL; + } + + memset(capsule, 0, sizeof(*capsule)); + capsule->name = strdup(name); + + TAILQ_INIT(&capsule->buckets); + vsr_domain_add(domain, capsule); + return capsule; +} + +/* + * Allocate a new VSR domain and add it to + * a specific process. + * + * @type: VSR type (e.g., VSR_FILE) + */ +struct vsr_domain * +vsr_new_domain(struct proc *td, vsr_domain_t type) +{ + struct vsr_domain *domain; + + /* Valid args? */ + if (type >= VSR_MAX_DOMAIN || td == NULL) { + return NULL; + } + + /* + * Do not overwrite the entry if it is + * already allocated and log this anomalous + * activity. + */ + if (td->vsr_tab[type] != NULL) { + pr_error("[security]: type %d already allocated\n", type); + return NULL; + } + + domain = dynalloc(sizeof(*domain)); + if (domain == NULL) { + return NULL; + } + + /* Initialize the domain */ + memset(domain, 0, sizeof(*domain)); + domain->type = type; + + td->vsr_tab[type] = domain; + return domain; +} + +/* + * Lookup a capsule by name for the current + * process. + */ +struct vsr_capsule * +vsr_lookup_capsule(struct proc *td, vsr_domain_t type, const char *name) +{ + struct vsr_domain *domain; + + if (td == NULL) { + return NULL; + } + + /* + * The VSR domain must be registered for + * us to lookup any capsules from it. + */ + if ((domain = td->vsr_tab[type]) == NULL) { + pr_error("VSR domain %d not registered\n", type); + return NULL; + } + + return vfs_domain_lookup(domain, name); +} + +/* + * Initialize per-process domains + */ +void +vsr_init_domains(struct proc *td) +{ + if (vsr_new_domain(td, VSR_FILE) == NULL) { + pr_error("failed to initialize VSR file domain\n"); + } +} + +/* + * Destroy per-process domains + */ +void +vsr_destroy_domains(struct proc *td) +{ + struct vsr_domain *domain; + + if (td == NULL) { + return; + } + + for (int i = 0; i < VSR_MAX_DOMAIN; ++i) { + if ((domain = td->vsr_tab[i]) == NULL) { + continue; + } + + vsr_destroy_table(&domain->table); + } +} |