diff options
Diffstat (limited to 'fsdev')
-rw-r--r-- | fsdev/file-op-9p.h | 2 | ||||
-rw-r--r-- | fsdev/virtfs-proxy-helper.c | 86 | ||||
-rw-r--r-- | fsdev/virtfs-proxy-helper.texi | 4 |
3 files changed, 89 insertions, 3 deletions
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index 7ef14afea3..1e96c8bed9 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -57,6 +57,8 @@ typedef struct extended_ops { */ #define V9FS_SM_NONE 0x00000010 #define V9FS_RDONLY 0x00000020 +#define V9FS_PROXY_SOCK_FD 0x00000040 +#define V9FS_PROXY_SOCK_NAME 0x00000080 #define V9FS_SEC_MASK 0x0000001C diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 52d748d93a..7f8def5b5d 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -57,6 +57,9 @@ static struct option helper_opts[] = { {"fd", required_argument, NULL, 'f'}, {"path", required_argument, NULL, 'p'}, {"nodaemon", no_argument, NULL, 'n'}, + {"socket", required_argument, NULL, 's'}, + {"uid", required_argument, NULL, 'u'}, + {"gid", required_argument, NULL, 'g'}, }; static bool is_daemon; @@ -695,11 +698,61 @@ err_out: return ret; } +/* create unix domain socket and return the descriptor */ +static int proxy_socket(const char *path, uid_t uid, gid_t gid) +{ + int sock, client; + struct sockaddr_un proxy, qemu; + socklen_t size; + + /* requested socket already exists, refuse to start */ + if (!access(path, F_OK)) { + do_log(LOG_CRIT, "socket already exists\n"); + return -1; + } + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + do_perror("socket"); + return -1; + } + + /* mask other part of mode bits */ + umask(7); + + proxy.sun_family = AF_UNIX; + strcpy(proxy.sun_path, path); + if (bind(sock, (struct sockaddr *)&proxy, + sizeof(struct sockaddr_un)) < 0) { + do_perror("bind"); + return -1; + } + if (chown(proxy.sun_path, uid, gid) < 0) { + do_perror("chown"); + return -1; + } + if (listen(sock, 1) < 0) { + do_perror("listen"); + return -1; + } + + client = accept(sock, (struct sockaddr *)&qemu, &size); + if (client < 0) { + do_perror("accept"); + return -1; + } + return client; +} + static void usage(char *prog) { fprintf(stderr, "usage: %s\n" " -p|--path <path> 9p path to export\n" " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n" + " {-s|--socket <socketname> socket file used for communication\n" + " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give " + " access to this socket\n" + " \tNote: -s & -f can not be used together\n" " [-n|--nodaemon] Run as a normal program\n", basename(prog)); } @@ -939,7 +992,10 @@ err_out: int main(int argc, char **argv) { int sock; + uid_t own_u; + gid_t own_g; char *rpath = NULL; + char *sock_name = NULL; struct stat stbuf; int c, option_index; #ifdef FS_IOC_GETVERSION @@ -949,9 +1005,10 @@ int main(int argc, char **argv) is_daemon = true; sock = -1; + own_u = own_g = -1; while (1) { option_index = 0; - c = getopt_long(argc, argv, "p:nh?f:", helper_opts, + c = getopt_long(argc, argv, "p:nh?f:s:u:g:", helper_opts, &option_index); if (c == -1) { break; @@ -966,6 +1023,15 @@ int main(int argc, char **argv) case 'f': sock = atoi(optarg); break; + case 's': + sock_name = strdup(optarg); + break; + case 'u': + own_u = atoi(optarg); + break; + case 'g': + own_g = atoi(optarg); + break; case '?': case 'h': default: @@ -975,8 +1041,16 @@ int main(int argc, char **argv) } /* Parameter validation */ - if (sock == -1 || rpath == NULL) { - fprintf(stderr, "socket descriptor or path not specified\n"); + if ((sock_name == NULL && sock == -1) || rpath == NULL) { + fprintf(stderr, "socket, socket descriptor or path not specified\n"); + usage(argv[0]); + return -1; + } + + if (*sock_name && (own_u == -1 || own_g == -1)) { + fprintf(stderr, "owner uid:gid not specified, "); + fprintf(stderr, + "owner uid:gid specifies who can access the socket file\n"); usage(argv[0]); exit(EXIT_FAILURE); } @@ -1001,6 +1075,12 @@ int main(int argc, char **argv) } do_log(LOG_INFO, "Started\n"); + if (*sock_name) { + sock = proxy_socket(sock_name, own_u, own_g); + if (sock < 0) { + goto error; + } + } get_version = false; #ifdef FS_IOC_GETVERSION diff --git a/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi index 3816382bb9..faa0434480 100644 --- a/fsdev/virtfs-proxy-helper.texi +++ b/fsdev/virtfs-proxy-helper.texi @@ -46,6 +46,10 @@ Path to export for proxy filesystem driver Use given file descriptor as socket descriptor for communicating with qemu proxy fs drier. Usually a helper like libvirt will create socketpair and pass one of the fds as parameter to -f|--fd +@item -s|--socket socket-file +Creates named socket file for communicating with qemu proxy fs driver +@item -u|--uid uid -g|--gid gid +uid:gid combination to give access to named socket file @item -n|--nodaemon Run as a normal program. By default program will run in daemon mode @end table |