Commit 7dc7030d authored by Andrei Vagin's avatar Andrei Vagin

fdstore: add synchronization to protect a peek offset

When we need to get a file descriptor, we have to set peek offset
and then to peek a message. There are two system calls, so we need
to be sure that nobody changes a socket peek offset after we set it.
Acked-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 4d06aa12
...@@ -6,12 +6,17 @@ ...@@ -6,12 +6,17 @@
#include <stdio.h> #include <stdio.h>
#include "common/scm.h" #include "common/scm.h"
#include "common/lock.h"
#include "servicefd.h" #include "servicefd.h"
#include "fdstore.h" #include "fdstore.h"
#include "xmalloc.h" #include "xmalloc.h"
#include "rst-malloc.h"
#include "log.h" #include "log.h"
static int next_id; static struct fdstore_desc {
int next_id;
mutex_t lock; /* to protect a peek offset */
} *desc;
int fdstore_init(void) int fdstore_init(void)
{ {
...@@ -20,6 +25,13 @@ int fdstore_init(void) ...@@ -20,6 +25,13 @@ int fdstore_init(void)
struct stat st; struct stat st;
int sk, ret; int sk, ret;
desc = shmalloc(sizeof(*desc));
if (!desc)
return -1;
desc->next_id = 0;
mutex_init(&desc->lock);
sk = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0); sk = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
if (sk < 0) { if (sk < 0) {
pr_perror("Unable to create a socket"); pr_perror("Unable to create a socket");
...@@ -67,13 +79,20 @@ int fdstore_init(void) ...@@ -67,13 +79,20 @@ int fdstore_init(void)
int fdstore_add(int fd) int fdstore_add(int fd)
{ {
int sk = get_service_fd(FDSTORE_SK_OFF); int sk = get_service_fd(FDSTORE_SK_OFF);
int id;
mutex_lock(&desc->lock);
if (send_fd(sk, NULL, 0, fd)) if (send_fd(sk, NULL, 0, fd)) {
mutex_unlock(&desc->lock);
return -1; return -1;
}
id = desc->next_id++;
next_id++; mutex_unlock(&desc->lock);
return next_id - 1; return id;
} }
int fdstore_get(int id) int fdstore_get(int id)
...@@ -81,14 +100,19 @@ int fdstore_get(int id) ...@@ -81,14 +100,19 @@ int fdstore_get(int id)
int sk = get_service_fd(FDSTORE_SK_OFF); int sk = get_service_fd(FDSTORE_SK_OFF);
int fd; int fd;
mutex_lock(&desc->lock);
if (setsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &id, sizeof(id))) { if (setsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &id, sizeof(id))) {
mutex_unlock(&desc->lock);
pr_perror("Unable to a peek offset"); pr_perror("Unable to a peek offset");
return -1; return -1;
} }
if (__recv_fds(sk, &fd, 1, NULL, 0, MSG_PEEK) < 0) { if (__recv_fds(sk, &fd, 1, NULL, 0, MSG_PEEK) < 0) {
mutex_unlock(&desc->lock);
pr_perror("Unable to get a file descriptor with the %d id", id); pr_perror("Unable to get a file descriptor with the %d id", id);
return -1; return -1;
} }
mutex_unlock(&desc->lock);
return fd; return fd;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment