]>
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.
12 #include <sys/socket.h>
19 #include <sys/resource.h>
24 #include <sys/capability.h>
25 #include <sys/fsuid.h>
30 #include <sys/ioctl.h>
32 #ifdef CONFIG_LINUX_MAGIC_H
33 #include <linux/magic.h>
35 #include "qemu-common.h"
36 #include "qemu-xattr.h"
37 #include "virtio-9p-marshal.h"
38 #include "hw/9pfs/virtio-9p-proxy.h"
39 #include "fsdev/virtio-9p-marshal.h"
41 #define PROGNAME "virtfs-proxy-helper"
43 #ifndef XFS_SUPER_MAGIC
44 #define XFS_SUPER_MAGIC 0x58465342
46 #ifndef EXT2_SUPER_MAGIC
47 #define EXT2_SUPER_MAGIC 0xEF53
49 #ifndef REISERFS_SUPER_MAGIC
50 #define REISERFS_SUPER_MAGIC 0x52654973
52 #ifndef BTRFS_SUPER_MAGIC
53 #define BTRFS_SUPER_MAGIC 0x9123683E
56 static struct option helper_opts
[] = {
57 {"fd", required_argument
, NULL
, 'f'},
58 {"path", required_argument
, NULL
, 'p'},
59 {"nodaemon", no_argument
, NULL
, 'n'},
60 {"socket", required_argument
, NULL
, 's'},
61 {"uid", required_argument
, NULL
, 'u'},
62 {"gid", required_argument
, NULL
, 'g'},
65 static bool is_daemon
;
66 static bool get_version
; /* IOC getversion IOCTL supported */
68 static void do_log(int loglevel
, const char *format
, ...)
74 vsyslog(LOG_CRIT
, format
, ap
);
76 vfprintf(stderr
, format
, ap
);
81 static void do_perror(const char *string
)
84 syslog(LOG_CRIT
, "%s:%s", string
, strerror(errno
));
86 fprintf(stderr
, "%s:%s\n", string
, strerror(errno
));
90 static int do_cap_set(cap_value_t
*cap_value
, int size
, int reset
)
95 * Start with an empty set and set permitted and effective
99 do_perror("cap_init");
102 if (cap_set_flag(caps
, CAP_PERMITTED
, size
, cap_value
, CAP_SET
) < 0) {
103 do_perror("cap_set_flag");
107 caps
= cap_get_proc();
109 do_perror("cap_get_proc");
113 if (cap_set_flag(caps
, CAP_EFFECTIVE
, size
, cap_value
, CAP_SET
) < 0) {
114 do_perror("cap_set_flag");
117 if (cap_set_proc(caps
) < 0) {
118 do_perror("cap_set_proc");
129 static int init_capabilities(void)
131 /* helper needs following capbabilities only */
132 cap_value_t cap_list
[] = {
141 return do_cap_set(cap_list
, ARRAY_SIZE(cap_list
), 1);
144 static int socket_read(int sockfd
, void *buff
, ssize_t size
)
146 ssize_t retval
, total
= 0;
149 retval
= read(sockfd
, buff
, size
);
154 if (errno
== EINTR
) {
166 static int socket_write(int sockfd
, void *buff
, ssize_t size
)
168 ssize_t retval
, total
= 0;
171 retval
= write(sockfd
, buff
, size
);
173 if (errno
== EINTR
) {
185 static int read_request(int sockfd
, struct iovec
*iovec
, ProxyHeader
*header
)
190 * read the request header.
193 retval
= socket_read(sockfd
, iovec
->iov_base
, PROXY_HDR_SZ
);
197 iovec
->iov_len
= PROXY_HDR_SZ
;
198 retval
= proxy_unmarshal(iovec
, 0, "dd", &header
->type
, &header
->size
);
203 * We can't process message.size > PROXY_MAX_IO_SZ.
204 * Treat it as fatal error
206 if (header
->size
> PROXY_MAX_IO_SZ
) {
209 retval
= socket_read(sockfd
, iovec
->iov_base
+ PROXY_HDR_SZ
, header
->size
);
213 iovec
->iov_len
+= header
->size
;
217 static int send_fd(int sockfd
, int fd
)
222 struct cmsghdr
*cmsg
;
223 union MsgControl msg_control
;
225 iov
.iov_base
= &data
;
226 iov
.iov_len
= sizeof(data
);
228 memset(&msg
, 0, sizeof(msg
));
231 /* No ancillary data on error */
233 /* fd is really negative errno if the request failed */
236 data
= V9FS_FD_VALID
;
237 msg
.msg_control
= &msg_control
;
238 msg
.msg_controllen
= sizeof(msg_control
);
240 cmsg
= &msg_control
.cmsg
;
241 cmsg
->cmsg_len
= CMSG_LEN(sizeof(fd
));
242 cmsg
->cmsg_level
= SOL_SOCKET
;
243 cmsg
->cmsg_type
= SCM_RIGHTS
;
244 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(fd
));
248 retval
= sendmsg(sockfd
, &msg
, 0);
249 } while (retval
< 0 && errno
== EINTR
);
259 static int send_status(int sockfd
, struct iovec
*iovec
, int status
)
262 int retval
, msg_size
;;
265 header
.type
= T_ERROR
;
267 header
.type
= T_SUCCESS
;
269 header
.size
= sizeof(status
);
271 * marshal the return status. We don't check error.
272 * because we are sure we have enough space for the status
274 msg_size
= proxy_marshal(iovec
, 0, "ddd", header
.type
,
275 header
.size
, status
);
276 retval
= socket_write(sockfd
, iovec
->iov_base
, msg_size
);
284 * from man 7 capabilities, section
285 * Effect of User ID Changes on Capabilities:
286 * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
287 * then the following capabilities are cleared from the effective set:
288 * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID,
289 * CAP_LINUX_IMMUTABLE (since Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
290 * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
291 * then any of these capabilities that are enabled in the permitted set
292 * are enabled in the effective set.
294 static int setfsugid(int uid
, int gid
)
297 * We still need DAC_OVERRIDE because we don't change
298 * supplementary group ids, and hence may be subjected DAC rules
300 cap_value_t cap_list
[] = {
307 if (uid
!= 0 || gid
!= 0) {
308 return do_cap_set(cap_list
, ARRAY_SIZE(cap_list
), 0);
314 * send response in two parts
316 * 2) Response or error status
317 * This function should be called with marshaled response
318 * send_response constructs header part and error part only.
319 * send response sends {ProxyHeader,Response} if the request was success
320 * otherwise sends {ProxyHeader,error status}
322 static int send_response(int sock
, struct iovec
*iovec
, int size
)
328 * If response size exceeds available iovec->iov_len,
331 if (size
> PROXY_MAX_IO_SZ
) {
337 * In case of error we would not have got the error encoded
338 * already so encode the error here.
340 header
.type
= T_ERROR
;
341 header
.size
= sizeof(size
);
342 proxy_marshal(iovec
, PROXY_HDR_SZ
, "d", size
);
344 header
.type
= T_SUCCESS
;
347 proxy_marshal(iovec
, 0, "dd", header
.type
, header
.size
);
348 retval
= socket_write(sock
, iovec
->iov_base
, header
.size
+ PROXY_HDR_SZ
);
356 * gets generation number
357 * returns -errno on failure and sizeof(generation number) on success
359 static int do_getversion(struct iovec
*iovec
, struct iovec
*out_iovec
)
362 int retval
= -ENOTTY
;
363 #ifdef FS_IOC_GETVERSION
369 /* no need to issue ioctl */
372 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
, "q", version
);
375 #ifdef FS_IOC_GETVERSION
376 retval
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "s", &path
);
381 fd
= open(path
.data
, O_RDONLY
);
386 if (ioctl(fd
, FS_IOC_GETVERSION
, &version
) < 0) {
389 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
, "q", version
);
393 v9fs_string_free(&path
);
398 static int do_getxattr(int type
, struct iovec
*iovec
, struct iovec
*out_iovec
)
400 int size
= 0, offset
, retval
;
401 V9fsString path
, name
, xattr
;
403 v9fs_string_init(&xattr
);
404 v9fs_string_init(&path
);
405 retval
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "ds", &size
, &path
);
409 offset
= PROXY_HDR_SZ
+ retval
;
412 xattr
.data
= g_malloc(size
);
417 v9fs_string_init(&name
);
418 retval
= proxy_unmarshal(iovec
, offset
, "s", &name
);
420 retval
= lgetxattr(path
.data
, name
.data
, xattr
.data
, size
);
427 v9fs_string_free(&name
);
430 retval
= llistxattr(path
.data
, xattr
.data
, size
);
443 proxy_marshal(out_iovec
, PROXY_HDR_SZ
, "d", retval
);
444 retval
= sizeof(retval
);
446 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
, "s", &xattr
);
449 v9fs_string_free(&xattr
);
450 v9fs_string_free(&path
);
454 static void stat_to_prstat(ProxyStat
*pr_stat
, struct stat
*stat
)
456 memset(pr_stat
, 0, sizeof(*pr_stat
));
457 pr_stat
->st_dev
= stat
->st_dev
;
458 pr_stat
->st_ino
= stat
->st_ino
;
459 pr_stat
->st_nlink
= stat
->st_nlink
;
460 pr_stat
->st_mode
= stat
->st_mode
;
461 pr_stat
->st_uid
= stat
->st_uid
;
462 pr_stat
->st_gid
= stat
->st_gid
;
463 pr_stat
->st_rdev
= stat
->st_rdev
;
464 pr_stat
->st_size
= stat
->st_size
;
465 pr_stat
->st_blksize
= stat
->st_blksize
;
466 pr_stat
->st_blocks
= stat
->st_blocks
;
467 pr_stat
->st_atim_sec
= stat
->st_atim
.tv_sec
;
468 pr_stat
->st_atim_nsec
= stat
->st_atim
.tv_nsec
;
469 pr_stat
->st_mtim_sec
= stat
->st_mtim
.tv_sec
;
470 pr_stat
->st_mtim_nsec
= stat
->st_mtim
.tv_nsec
;
471 pr_stat
->st_ctim_sec
= stat
->st_ctim
.tv_sec
;
472 pr_stat
->st_ctim_nsec
= stat
->st_ctim
.tv_nsec
;
475 static void statfs_to_prstatfs(ProxyStatFS
*pr_stfs
, struct statfs
*stfs
)
477 memset(pr_stfs
, 0, sizeof(*pr_stfs
));
478 pr_stfs
->f_type
= stfs
->f_type
;
479 pr_stfs
->f_bsize
= stfs
->f_bsize
;
480 pr_stfs
->f_blocks
= stfs
->f_blocks
;
481 pr_stfs
->f_bfree
= stfs
->f_bfree
;
482 pr_stfs
->f_bavail
= stfs
->f_bavail
;
483 pr_stfs
->f_files
= stfs
->f_files
;
484 pr_stfs
->f_ffree
= stfs
->f_ffree
;
485 pr_stfs
->f_fsid
[0] = stfs
->f_fsid
.__val
[0];
486 pr_stfs
->f_fsid
[1] = stfs
->f_fsid
.__val
[1];
487 pr_stfs
->f_namelen
= stfs
->f_namelen
;
488 pr_stfs
->f_frsize
= stfs
->f_frsize
;
492 * Gets stat/statfs information and packs in out_iovec structure
493 * on success returns number of bytes packed in out_iovec struture
494 * otherwise returns -errno
496 static int do_stat(int type
, struct iovec
*iovec
, struct iovec
*out_iovec
)
503 struct statfs stfs_buf
;
505 v9fs_string_init(&path
);
506 retval
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "s", &path
);
513 retval
= lstat(path
.data
, &st_buf
);
517 stat_to_prstat(&pr_stat
, &st_buf
);
518 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
,
519 "qqqdddqqqqqqqqqq", pr_stat
.st_dev
,
520 pr_stat
.st_ino
, pr_stat
.st_nlink
,
521 pr_stat
.st_mode
, pr_stat
.st_uid
,
522 pr_stat
.st_gid
, pr_stat
.st_rdev
,
523 pr_stat
.st_size
, pr_stat
.st_blksize
,
525 pr_stat
.st_atim_sec
, pr_stat
.st_atim_nsec
,
526 pr_stat
.st_mtim_sec
, pr_stat
.st_mtim_nsec
,
527 pr_stat
.st_ctim_sec
, pr_stat
.st_ctim_nsec
);
531 retval
= statfs(path
.data
, &stfs_buf
);
535 statfs_to_prstatfs(&pr_stfs
, &stfs_buf
);
536 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
,
537 "qqqqqqqqqqq", pr_stfs
.f_type
,
538 pr_stfs
.f_bsize
, pr_stfs
.f_blocks
,
539 pr_stfs
.f_bfree
, pr_stfs
.f_bavail
,
540 pr_stfs
.f_files
, pr_stfs
.f_ffree
,
541 pr_stfs
.f_fsid
[0], pr_stfs
.f_fsid
[1],
542 pr_stfs
.f_namelen
, pr_stfs
.f_frsize
);
546 v9fs_string_free(&path
);
550 static int do_readlink(struct iovec
*iovec
, struct iovec
*out_iovec
)
554 V9fsString target
, path
;
556 v9fs_string_init(&path
);
557 retval
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "sd", &path
, &size
);
559 v9fs_string_free(&path
);
562 buffer
= g_malloc(size
);
563 v9fs_string_init(&target
);
564 retval
= readlink(path
.data
, buffer
, size
);
566 buffer
[retval
] = '\0';
567 v9fs_string_sprintf(&target
, "%s", buffer
);
568 retval
= proxy_marshal(out_iovec
, PROXY_HDR_SZ
, "s", &target
);
573 v9fs_string_free(&target
);
574 v9fs_string_free(&path
);
579 * create other filesystem objects and send 0 on success
580 * return -errno on error
582 static int do_create_others(int type
, struct iovec
*iovec
)
586 int offset
= PROXY_HDR_SZ
;
587 V9fsString oldpath
, path
;
588 int mode
, uid
, gid
, cur_uid
, cur_gid
;
590 v9fs_string_init(&path
);
591 v9fs_string_init(&oldpath
);
595 retval
= proxy_unmarshal(iovec
, offset
, "dd", &uid
, &gid
);
600 retval
= setfsugid(uid
, gid
);
607 retval
= proxy_unmarshal(iovec
, offset
, "sdq", &path
, &mode
, &rdev
);
611 retval
= mknod(path
.data
, mode
, rdev
);
614 retval
= proxy_unmarshal(iovec
, offset
, "sd", &path
, &mode
);
618 retval
= mkdir(path
.data
, mode
);
621 retval
= proxy_unmarshal(iovec
, offset
, "ss", &oldpath
, &path
);
625 retval
= symlink(oldpath
.data
, path
.data
);
633 v9fs_string_free(&path
);
634 v9fs_string_free(&oldpath
);
635 setfsugid(cur_uid
, cur_gid
);
640 * create a file and send fd on success
641 * return -errno on error
643 static int do_create(struct iovec
*iovec
)
647 int flags
, mode
, uid
, gid
, cur_uid
, cur_gid
;
649 v9fs_string_init(&path
);
650 ret
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "sdddd",
651 &path
, &flags
, &mode
, &uid
, &gid
);
653 goto unmarshal_err_out
;
657 ret
= setfsugid(uid
, gid
);
660 * On failure reset back to the
666 ret
= open(path
.data
, flags
, mode
);
672 setfsugid(cur_uid
, cur_gid
);
674 v9fs_string_free(&path
);
679 * open a file and send fd on success
680 * return -errno on error
682 static int do_open(struct iovec
*iovec
)
687 v9fs_string_init(&path
);
688 ret
= proxy_unmarshal(iovec
, PROXY_HDR_SZ
, "sd", &path
, &flags
);
692 ret
= open(path
.data
, flags
);
697 v9fs_string_free(&path
);
701 /* create unix domain socket and return the descriptor */
702 static int proxy_socket(const char *path
, uid_t uid
, gid_t gid
)
705 struct sockaddr_un proxy
, qemu
;
708 /* requested socket already exists, refuse to start */
709 if (!access(path
, F_OK
)) {
710 do_log(LOG_CRIT
, "socket already exists\n");
714 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
720 /* mask other part of mode bits */
723 proxy
.sun_family
= AF_UNIX
;
724 strcpy(proxy
.sun_path
, path
);
725 if (bind(sock
, (struct sockaddr
*)&proxy
,
726 sizeof(struct sockaddr_un
)) < 0) {
730 if (chown(proxy
.sun_path
, uid
, gid
) < 0) {
734 if (listen(sock
, 1) < 0) {
739 client
= accept(sock
, (struct sockaddr
*)&qemu
, &size
);
747 static void usage(char *prog
)
749 fprintf(stderr
, "usage: %s\n"
750 " -p|--path <path> 9p path to export\n"
751 " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
752 " {-s|--socket <socketname> socket file used for communication\n"
753 " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give "
754 " access to this socket\n"
755 " \tNote: -s & -f can not be used together\n"
756 " [-n|--nodaemon] Run as a normal program\n",
760 static int process_reply(int sock
, int type
,
761 struct iovec
*out_iovec
, int retval
)
766 if (send_fd(sock
, retval
) < 0) {
782 if (send_status(sock
, out_iovec
, retval
) < 0) {
792 if (send_response(sock
, out_iovec
, retval
) < 0) {
803 static int process_requests(int sock
)
811 V9fsString name
, value
;
812 struct timespec spec
[2];
813 V9fsString oldpath
, path
;
814 struct iovec in_iovec
, out_iovec
;
816 in_iovec
.iov_base
= g_malloc(PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
);
817 in_iovec
.iov_len
= PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
;
818 out_iovec
.iov_base
= g_malloc(PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
);
819 out_iovec
.iov_len
= PROXY_MAX_IO_SZ
+ PROXY_HDR_SZ
;
823 * initialize the header type, so that we send
824 * response to proper request type.
827 retval
= read_request(sock
, &in_iovec
, &header
);
832 switch (header
.type
) {
834 retval
= do_open(&in_iovec
);
837 retval
= do_create(&in_iovec
);
842 retval
= do_create_others(header
.type
, &in_iovec
);
845 v9fs_string_init(&path
);
846 v9fs_string_init(&oldpath
);
847 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
,
848 "ss", &oldpath
, &path
);
850 retval
= link(oldpath
.data
, path
.data
);
855 v9fs_string_free(&oldpath
);
856 v9fs_string_free(&path
);
860 retval
= do_stat(header
.type
, &in_iovec
, &out_iovec
);
863 retval
= do_readlink(&in_iovec
, &out_iovec
);
866 v9fs_string_init(&path
);
867 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
,
870 retval
= chmod(path
.data
, mode
);
875 v9fs_string_free(&path
);
878 v9fs_string_init(&path
);
879 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
, "sdd", &path
,
882 retval
= lchown(path
.data
, uid
, gid
);
887 v9fs_string_free(&path
);
890 v9fs_string_init(&path
);
891 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
, "sq",
894 retval
= truncate(path
.data
, offset
);
899 v9fs_string_free(&path
);
902 v9fs_string_init(&path
);
903 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
, "sqqqq", &path
,
904 &spec
[0].tv_sec
, &spec
[0].tv_nsec
,
905 &spec
[1].tv_sec
, &spec
[1].tv_nsec
);
907 retval
= qemu_utimens(path
.data
, spec
);
912 v9fs_string_free(&path
);
915 v9fs_string_init(&path
);
916 v9fs_string_init(&oldpath
);
917 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
,
918 "ss", &oldpath
, &path
);
920 retval
= rename(oldpath
.data
, path
.data
);
925 v9fs_string_free(&oldpath
);
926 v9fs_string_free(&path
);
929 v9fs_string_init(&path
);
930 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
, "s", &path
);
932 retval
= remove(path
.data
);
937 v9fs_string_free(&path
);
941 retval
= do_getxattr(header
.type
, &in_iovec
, &out_iovec
);
944 v9fs_string_init(&path
);
945 v9fs_string_init(&name
);
946 v9fs_string_init(&value
);
947 retval
= proxy_unmarshal(&in_iovec
, PROXY_HDR_SZ
, "sssdd", &path
,
948 &name
, &value
, &size
, &flags
);
950 retval
= lsetxattr(path
.data
,
951 name
.data
, value
.data
, size
, flags
);
956 v9fs_string_free(&path
);
957 v9fs_string_free(&name
);
958 v9fs_string_free(&value
);
961 v9fs_string_init(&path
);
962 v9fs_string_init(&name
);
963 retval
= proxy_unmarshal(&in_iovec
,
964 PROXY_HDR_SZ
, "ss", &path
, &name
);
966 retval
= lremovexattr(path
.data
, name
.data
);
971 v9fs_string_free(&path
);
972 v9fs_string_free(&name
);
975 retval
= do_getversion(&in_iovec
, &out_iovec
);
982 if (process_reply(sock
, header
.type
, &out_iovec
, retval
) < 0) {
987 g_free(in_iovec
.iov_base
);
988 g_free(out_iovec
.iov_base
);
992 int main(int argc
, char **argv
)
998 char *sock_name
= NULL
;
1000 int c
, option_index
;
1001 #ifdef FS_IOC_GETVERSION
1003 struct statfs st_fs
;
1011 c
= getopt_long(argc
, argv
, "p:nh?f:s:u:g:", helper_opts
,
1018 rpath
= strdup(optarg
);
1024 sock
= atoi(optarg
);
1027 sock_name
= strdup(optarg
);
1030 own_u
= atoi(optarg
);
1033 own_g
= atoi(optarg
);
1043 /* Parameter validation */
1044 if ((sock_name
== NULL
&& sock
== -1) || rpath
== NULL
) {
1045 fprintf(stderr
, "socket, socket descriptor or path not specified\n");
1050 if (*sock_name
&& (own_u
== -1 || own_g
== -1)) {
1051 fprintf(stderr
, "owner uid:gid not specified, ");
1053 "owner uid:gid specifies who can access the socket file\n");
1058 if (lstat(rpath
, &stbuf
) < 0) {
1059 fprintf(stderr
, "invalid path \"%s\" specified, %s\n",
1060 rpath
, strerror(errno
));
1064 if (!S_ISDIR(stbuf
.st_mode
)) {
1065 fprintf(stderr
, "specified path \"%s\" is not directory\n", rpath
);
1070 if (daemon(0, 0) < 0) {
1071 fprintf(stderr
, "daemon call failed\n");
1074 openlog(PROGNAME
, LOG_PID
, LOG_DAEMON
);
1077 do_log(LOG_INFO
, "Started\n");
1079 sock
= proxy_socket(sock_name
, own_u
, own_g
);
1085 get_version
= false;
1086 #ifdef FS_IOC_GETVERSION
1087 /* check whether underlying FS support IOC_GETVERSION */
1088 retval
= statfs(rpath
, &st_fs
);
1090 switch (st_fs
.f_type
) {
1091 case EXT2_SUPER_MAGIC
:
1092 case BTRFS_SUPER_MAGIC
:
1093 case REISERFS_SUPER_MAGIC
:
1094 case XFS_SUPER_MAGIC
:
1101 if (chdir("/") < 0) {
1105 if (chroot(rpath
) < 0) {
1106 do_perror("chroot");
1111 if (init_capabilities() < 0) {
1115 process_requests(sock
);
1117 do_log(LOG_INFO
, "Done\n");