diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h index 2bbe22ea9..798d07519 100644 --- a/include/qb/qbipcs.h +++ b/include/qb/qbipcs.h @@ -117,6 +117,8 @@ struct qb_ipcs_poll_handlers { * The type of checks you should do are authentication, service availabilty * or process resource constraints. * @return 0 to accept or -errno to indicate a failure (sent back to the client) + * + * @note you can call qb_ipcs_connection_auth_set() within this function. */ typedef int32_t (*qb_ipcs_connection_accept_fn) (qb_ipcs_connection_t *c, uid_t uid, gid_t gid); @@ -377,6 +379,23 @@ qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_t* pt); qb_ipcs_connection_t * qb_ipcs_connection_next_get(qb_ipcs_service_t* pt, qb_ipcs_connection_t *current); +/** + * Set the permissions on and shared memory files so that both processes can + * read and write to them. + * + * @param conn connection instance + * @param uid the user id to set. + * @param gid the group id to set. + * @param mode the mode to set. + * + * @see chmod() chown() + * @note this must be called within the qb_ipcs_connection_accept_fn() + * callback. + */ +void qb_ipcs_connection_auth_set(qb_ipcs_connection_t *conn, uid_t uid, + gid_t gid, mode_t mode); + + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/include/qb/qbrb.h b/include/qb/qbrb.h index 8a012bd1c..fd37626a1 100644 --- a/include/qb/qbrb.h +++ b/include/qb/qbrb.h @@ -285,6 +285,14 @@ qb_ringbuffer_t *qb_rb_create_from_file(int32_t fd, uint32_t flags); */ int32_t qb_rb_chown(qb_ringbuffer_t * rb, uid_t owner, gid_t group); +/** + * Like 'chmod' it changes the mode of the ringbuffers resources. + * @param mode mode to change to + * @param rb ringbuffer instance + * @retval 0 == ok + * @retval -errno for error + */ +int32_t qb_rb_chmod(qb_ringbuffer_t * rb, mode_t mode); /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/lib/ipc_int.h b/lib/ipc_int.h index a569a808d..14f20914b 100644 --- a/lib/ipc_int.h +++ b/lib/ipc_int.h @@ -156,12 +156,19 @@ enum qb_ipcs_connection_state { #define CONNECTION_DESCRIPTION (16) +struct qb_ipcs_connection_auth { + uid_t uid; + gid_t gid; + mode_t mode; +}; + struct qb_ipcs_connection { enum qb_ipcs_connection_state state; int32_t refcount; pid_t pid; uid_t euid; gid_t egid; + struct qb_ipcs_connection_auth auth; struct qb_ipc_one_way setup; struct qb_ipc_one_way request; struct qb_ipc_one_way response; diff --git a/lib/ipc_shm.c b/lib/ipc_shm.c index 19c978821..3e823ea80 100644 --- a/lib/ipc_shm.c +++ b/lib/ipc_shm.c @@ -233,6 +233,40 @@ qb_ipcs_shm_disconnect(struct qb_ipcs_connection *c) } } +static int32_t +qb_ipcs_shm_rb_open(struct qb_ipcs_connection *c, + struct qb_ipc_one_way *ow, + const char *rb_name) +{ + int32_t res = 0; + + ow->u.shm.rb = qb_rb_open(rb_name, + ow->max_msg_size, + QB_RB_FLAG_CREATE | + QB_RB_FLAG_SHARED_PROCESS, + sizeof(int32_t)); + if (ow->u.shm.rb == NULL) { + res = -errno; + qb_util_perror(LOG_ERR, "qb_rb_open:%s", rb_name); + return res; + } + res = qb_rb_chown(ow->u.shm.rb, c->auth.uid, c->auth.gid); + if (res != 0) { + qb_util_perror(LOG_ERR, "qb_rb_chown:%s", rb_name); + goto cleanup; + } + res = qb_rb_chmod(ow->u.shm.rb, c->auth.mode); + if (res != 0) { + qb_util_perror(LOG_ERR, "qb_rb_chmod:%s", rb_name); + goto cleanup; + } + return res; + +cleanup: + qb_rb_close(ow->u.shm.rb); + return res; +} + static int32_t qb_ipcs_shm_connect(struct qb_ipcs_service *s, struct qb_ipcs_connection *c, @@ -249,59 +283,27 @@ qb_ipcs_shm_connect(struct qb_ipcs_service *s, snprintf(r->event, NAME_MAX, "%s-event-%s", s->name, c->description); - c->request.u.shm.rb = qb_rb_open(r->request, - c->request.max_msg_size, - QB_RB_FLAG_CREATE | - QB_RB_FLAG_SHARED_PROCESS, - sizeof(int32_t)); - if (c->request.u.shm.rb == NULL) { - res = -errno; - qb_util_perror(LOG_ERR, "qb_rb_open:%s", r->request); - goto cleanup; - } - res = qb_rb_chown(c->request.u.shm.rb, c->euid, c->egid); + res = qb_ipcs_shm_rb_open(c, &c->request, + r->request); if (res != 0) { - qb_util_perror(LOG_ERR, "qb_rb_chown:%s", r->request); goto cleanup; } - c->response.u.shm.rb = qb_rb_open(r->response, - c->response.max_msg_size, - QB_RB_FLAG_CREATE | - QB_RB_FLAG_SHARED_PROCESS, 0); - if (c->response.u.shm.rb == NULL) { - res = -errno; - qb_util_perror(LOG_ERR, "qb_rb_open:%s", r->response); - goto cleanup_request; - } - res = qb_rb_chown(c->response.u.shm.rb, c->euid, c->egid); + res = qb_ipcs_shm_rb_open(c, &c->response, + r->response); if (res != 0) { - qb_util_perror(LOG_ERR, "qb_rb_chown:%s", r->response); goto cleanup_request; } - c->event.u.shm.rb = qb_rb_open(r->event, - c->event.max_msg_size, - QB_RB_FLAG_CREATE | - QB_RB_FLAG_SHARED_PROCESS, 0); - - if (c->event.u.shm.rb == NULL) { - res = -errno; - qb_util_perror(LOG_ERR, "qb_rb_open:%s", r->event); - goto cleanup_request_response; - } - res = qb_rb_chown(c->event.u.shm.rb, c->euid, c->egid); + res = qb_ipcs_shm_rb_open(c, &c->event, + r->event); if (res != 0) { - qb_util_perror(LOG_ERR, "qb_rb_chown:%s", r->event); - goto cleanup_all; + goto cleanup_request_response; } r->hdr.error = 0; return 0; -cleanup_all: - qb_rb_close(c->event.u.shm.rb); - cleanup_request_response: qb_rb_close(c->request.u.shm.rb); diff --git a/lib/ipc_us.c b/lib/ipc_us.c index 2808708ba..8808afdc1 100644 --- a/lib/ipc_us.c +++ b/lib/ipc_us.c @@ -615,8 +615,9 @@ handle_new_connection(struct qb_ipcs_service *s, c->response.max_msg_size = req->max_msg_size; c->event.max_msg_size = req->max_msg_size; c->pid = ugp->pid; - c->euid = ugp->uid; - c->egid = ugp->gid; + c->auth.uid = c->euid = ugp->uid; + c->auth.gid = c->egid = ugp->gid; + c->auth.mode = 0600; c->stats.client_pid = ugp->pid; snprintf(c->description, CONNECTION_DESCRIPTION, "%d-%d-%d", s->pid, ugp->pid, @@ -949,12 +950,19 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s, } (void)strlcpy(r->request, path, PATH_MAX); (void)strlcpy(c->request.u.us.shared_file_name, r->request, NAME_MAX); - res = chown(r->request, c->euid, c->egid); + res = chown(r->request, c->auth.uid, c->auth.gid); if (res != 0) { /* ignore res, this is just for the compiler warnings. */ res = 0; } + res = chmod(r->request, c->auth.mode); + if (res != 0) { + /* ignore res, this is just for the compiler warnings. + */ + res = 0; + } + shm_ptr = mmap(0, SHM_CONTROL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_hdr, 0); diff --git a/lib/ipcs.c b/lib/ipcs.c index 8370c7da8..68cb0a877 100644 --- a/lib/ipcs.c +++ b/lib/ipcs.c @@ -864,3 +864,14 @@ qb_ipcs_stats_get(struct qb_ipcs_service * s, } return 0; } + +void +qb_ipcs_connection_auth_set(qb_ipcs_connection_t *c, uid_t uid, + gid_t gid, mode_t mode) +{ + if (c) { + c->auth.uid = uid; + c->auth.gid = gid; + c->auth.mode = mode; + } +} diff --git a/lib/ringbuffer.c b/lib/ringbuffer.c index 1daa0a968..7902dcd70 100644 --- a/lib/ringbuffer.c +++ b/lib/ringbuffer.c @@ -769,3 +769,22 @@ qb_rb_chown(struct qb_ringbuffer_s * rb, uid_t owner, gid_t group) } return 0; } + +int32_t +qb_rb_chmod(qb_ringbuffer_t * rb, mode_t mode) +{ + int32_t res; + + if (rb == NULL) { + return -EINVAL; + } + res = chmod(rb->shared_hdr->data_path, mode); + if (res < 0) { + return -errno; + } + res = chmod(rb->shared_hdr->hdr_path, mode); + if (res < 0) { + return -errno; + } + return 0; +}