summaryrefslogtreecommitdiff
path: root/src/irmd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/main.c')
-rw-r--r--src/irmd/main.c87
1 files changed, 72 insertions, 15 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 5b787a24..ccb16017 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -22,6 +22,7 @@
#if defined(__linux__) || defined(__CYGWIN__)
#define _DEFAULT_SOURCE
+#define _GNU_SOURCE
#else
#define _POSIX_C_SOURCE 200809L
#endif
@@ -39,6 +40,7 @@
#include <ouroboros/list.h>
#include <ouroboros/lockfile.h>
#include <ouroboros/logs.h>
+#include <ouroboros/protobuf.h>
#include <ouroboros/pthread.h>
#include <ouroboros/random.h>
#include <ouroboros/rib.h>
@@ -56,6 +58,8 @@
#include "configfile.h"
#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
@@ -770,18 +774,47 @@ static int name_unreg(const char * name,
return -1;
}
+static int get_peer_ids(int fd,
+ uid_t * uid,
+ gid_t * gid)
+{
+#if defined(__linux__)
+ struct ucred ucred;
+ socklen_t len;
+
+ len = sizeof(ucred);
+
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0)
+ goto fail;
+
+ *uid = ucred.uid;
+ *gid = ucred.gid;
+#else
+ if (getpeereid(fd, uid, gid) < 0)
+ goto fail;
+#endif
+ return 0;
+ fail:
+ return -1;
+}
+
static int proc_announce(const struct proc_info * info)
{
+ if (reg_prepare_pool(info->uid, info->gid) < 0) {
+ log_err("Failed to prepare pool for uid %d.", info->uid);
+ goto fail;
+ }
+
if (reg_create_proc(info) < 0) {
log_err("Failed to add process %d.", info->pid);
- goto fail_proc;
+ goto fail;
}
log_info("Process added: %d (%s).", info->pid, info->prog);
return 0;
- fail_proc:
+ fail:
return -1;
}
@@ -868,6 +901,8 @@ static int flow_accept(struct flow_info * flow,
log_dbg("IPCP %d accepting flow %d for %s.",
flow->n_pid, flow->id, name);
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
err = oap_srv_process(&info, req_hdr, &resp_hdr, data, sk);
if (err < 0) {
log_err("OAP processing failed for %s.", name);
@@ -879,7 +914,8 @@ static int flow_accept(struct flow_info * flow,
goto fail_resp;
}
- log_info("Flow %d accepted by %d for %s.", flow->id, flow->n_pid, name);
+ log_info("Flow %d accepted by %d for %s (uid %d).",
+ flow->id, flow->n_pid, name, flow->uid);
freebuf(req_hdr);
freebuf(resp_hdr);
@@ -911,14 +947,17 @@ static int flow_join(struct flow_info * flow,
buffer_t pbuf = BUF_INIT; /* nothing to piggyback */
int err;
- log_info("Allocating flow for %d to %s.", flow->n_pid, dst);
-
if (reg_create_flow(flow) < 0) {
log_err("Failed to create flow.");
err = -EBADF;
goto fail_flow;
}
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
+ log_info("Allocating flow for %d to %s (uid %d).",
+ flow->n_pid, dst, flow->uid);
+
strcpy(layer.name, dst);
if (reg_get_ipcp_by_layer(&ipcp, &layer) < 0) {
log_err("Failed to get IPCP for layer %s.", dst);
@@ -1053,8 +1092,6 @@ static int flow_alloc(const char * dst,
/* piggyback of user data not yet implemented */
assert(data != NULL && BUF_IS_EMPTY(data));
- log_info("Allocating flow for %d to %s.", flow->n_pid, dst);
-
/* Look up name_info for dst */
if (reg_get_name_info(dst, &info) < 0) {
log_err("Failed to get name info for %s.", dst);
@@ -1068,6 +1105,11 @@ static int flow_alloc(const char * dst,
goto fail_flow;
}
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
+ log_info("Allocating flow for %d to %s (uid %d).",
+ flow->n_pid, dst, flow->uid);
+
if (get_ipcp_by_dst(dst, &flow->n_1_pid, &hash) < 0) {
log_err("Failed to find IPCP for %s.", dst);
err = -EIPCP;
@@ -1332,7 +1374,8 @@ static void __cleanup_irm_msg(void * o)
irm_msg__free_unpacked((irm_msg_t *) o, NULL);
}
-static irm_msg_t * do_command_msg(irm_msg_t * msg)
+static irm_msg_t * do_command_msg(irm_msg_t * msg,
+ int fd)
{
struct ipcp_config conf;
struct ipcp_info ipcp;
@@ -1413,7 +1456,11 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
case IRM_MSG_CODE__IRM_PROC_ANNOUNCE:
proc.pid = msg->pid;
strcpy(proc.prog, msg->prog);
- res = proc_announce(&proc);
+ res = get_peer_ids(fd, &proc.uid, &proc.gid);
+ if (res < 0)
+ log_err("Failed to get UID/GID for pid %d.", msg->pid);
+ else
+ res = proc_announce(&proc);
break;
case IRM_MSG_CODE__IRM_PROC_EXIT:
res = proc_exit(msg->pid);
@@ -1598,7 +1645,7 @@ static void * mainloop(void * o)
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(__cleanup_irm_msg, msg);
- ret_msg = do_command_msg(msg);
+ ret_msg = do_command_msg(msg, sfd);
pthread_cleanup_pop(true);
pthread_cleanup_pop(false);
@@ -1691,7 +1738,7 @@ static void destroy_mount(char * mnt)
static int ouroboros_reset(void)
{
- ssm_pool_purge();
+ ssm_pool_gspp_purge();
lockfile_destroy(irmd.lf);
return 0;
@@ -1813,6 +1860,8 @@ static int irm_load_store(char * dpath)
static int irm_init(void)
{
struct stat st;
+ struct group * grp;
+ gid_t gid;
pthread_condattr_t cattr;
#ifdef HAVE_FUSE
mode_t mask;
@@ -1898,8 +1947,17 @@ static int irm_init(void)
goto fail_sock_path;
}
- if ((irmd.gspp = ssm_pool_create()) == NULL) {
- log_err("Failed to create pool.");
+ grp = getgrnam("ouroboros");
+ if (grp == NULL) {
+ log_warn("ouroboros group not found, using gid %d.", getgid());
+ gid = getgid();
+ } else {
+ gid = grp->gr_gid;
+ }
+
+ irmd.gspp = ssm_pool_create(getuid(), gid);
+ if (irmd.gspp == NULL) {
+ log_err("Failed to create GSPP.");
goto fail_pool;
}
@@ -2006,8 +2064,7 @@ static void irm_fini(void)
if (unlink(IRM_SOCK_PATH))
log_dbg("Failed to unlink %s.", IRM_SOCK_PATH);
- if (irmd.gspp != NULL)
- ssm_pool_destroy(irmd.gspp);
+ ssm_pool_destroy(irmd.gspp);
if (irmd.lf != NULL)
lockfile_destroy(irmd.lf);