]>
git.proxmox.com Git - mirror_qemu.git/blob - fsdev/virtfs-proxy-helper.c
2 * Helper for QEMU Proxy FS Driver
3 * Copyright IBM, Corp. 2011
6 * M. Mohan Kumar <mohan@in.ibm.com>
8 * This work is licensed under the terms of the GNU GPL, version 2. See
9 * the COPYING file in the top-level directory.
18 #include <sys/resource.h>
23 #include <sys/capability.h>
24 #include <sys/fsuid.h>
27 #include "qemu-common.h"
28 #include "virtio-9p-marshal.h"
29 #include "hw/9pfs/virtio-9p-proxy.h"
31 #define PROGNAME "virtfs-proxy-helper"
33 static struct option helper_opts
[] = {
34 {"fd", required_argument
, NULL
, 'f'},
35 {"path", required_argument
, NULL
, 'p'},
36 {"nodaemon", no_argument
, NULL
, 'n'},
39 static bool is_daemon
;
41 static void do_log(int loglevel
, const char *format
, ...)
47 vsyslog(LOG_CRIT
, format
, ap
);
49 vfprintf(stderr
, format
, ap
);
54 static void do_perror(const char *string
)
57 syslog(LOG_CRIT
, "%s:%s", string
, strerror(errno
));
59 fprintf(stderr
, "%s:%s\n", string
, strerror(errno
));
63 static int do_cap_set(cap_value_t
*cap_value
, int size
, int reset
)
68 * Start with an empty set and set permitted and effective
72 do_perror("cap_init");
75 if (cap_set_flag(caps
, CAP_PERMITTED
, size
, cap_value
, CAP_SET
) < 0) {
76 do_perror("cap_set_flag");
80 caps
= cap_get_proc();
82 do_perror("cap_get_proc");
86 if (cap_set_flag(caps
, CAP_EFFECTIVE
, size
, cap_value
, CAP_SET
) < 0) {
87 do_perror("cap_set_flag");
90 if (cap_set_proc(caps
) < 0) {
91 do_perror("cap_set_proc");
102 static int init_capabilities(void)
104 /* helper needs following capbabilities only */
105 cap_value_t cap_list
[] = {
114 return do_cap_set(cap_list
, ARRAY_SIZE(cap_list
), 1);
117 static int socket_read(int sockfd
, void *buff
, ssize_t size
)
119 ssize_t retval
, total
= 0;
122 retval
= read(sockfd
, buff
, size
);
127 if (errno
== EINTR
) {
139 static int socket_write(int sockfd
, void *buff
, ssize_t size
)
141 ssize_t retval
, total
= 0;
144 retval
= write(sockfd
, buff
, size
);
146 if (errno
== EINTR
) {
158 static int read_request(int sockfd
, struct iovec
*iovec
, ProxyHeader
*header
)
163 * read the request header.
166 retval
= socket_read(sockfd
, iovec
->iov_base
, PROXY_HDR_SZ
);
170 iovec
->iov_len
= PROXY_HDR_SZ
;
171 retval
= proxy_unmarshal(iovec
, 0, "dd", &header
->type
, &header
->size
);
176 * We can't process message.size > PROXY_MAX_IO_SZ.
177 * Treat it as fatal error
179 if (header
->size
> PROXY_MAX_IO_SZ
) {
182 retval
= socket_read(sockfd
, iovec
->iov_base
+ PROXY_HDR_SZ
, header
->size
);
186 iovec
->iov_len
+= header
->size
;
190 static void usage(char *prog
)
192 fprintf(stderr
, "usage: %s\n"
193 " -p|--path <path> 9p path to export\n"
194 " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
195 " [-n|--nodaemon] Run as a normal program\n",
199 static int process_requests(int sock
)
203 struct iovec in_iovec
;
205 in_iovec
.iov_base
= g_malloc(PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
);
206 in_iovec
.iov_len
= PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
;
208 retval
= read_request(sock
, &in_iovec
, &header
);
215 g_free(in_iovec
.iov_base
);
219 int main(int argc
, char **argv
)
230 c
= getopt_long(argc
, argv
, "p:nh?f:", helper_opts
,
237 rpath
= strdup(optarg
);
253 /* Parameter validation */
254 if (sock
== -1 || rpath
== NULL
) {
255 fprintf(stderr
, "socket descriptor or path not specified\n");
260 if (lstat(rpath
, &stbuf
) < 0) {
261 fprintf(stderr
, "invalid path \"%s\" specified, %s\n",
262 rpath
, strerror(errno
));
266 if (!S_ISDIR(stbuf
.st_mode
)) {
267 fprintf(stderr
, "specified path \"%s\" is not directory\n", rpath
);
272 if (daemon(0, 0) < 0) {
273 fprintf(stderr
, "daemon call failed\n");
276 openlog(PROGNAME
, LOG_PID
, LOG_DAEMON
);
279 do_log(LOG_INFO
, "Started\n");
281 if (chdir("/") < 0) {
285 if (chroot(rpath
) < 0) {
291 if (init_capabilities() < 0) {
295 process_requests(sock
);
297 do_log(LOG_INFO
, "Done\n");