2 * Privileged helper to handle persistent reservation commands for QEMU
4 * Copyright (C) 2017 Red Hat, Inc. <pbonzini@redhat.com>
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; under version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include <sys/ioctl.h>
24 #include <linux/dm-ioctl.h>
33 #include "qapi/error.h"
34 #include "qemu-common.h"
35 #include "qemu/cutils.h"
36 #include "qemu/main-loop.h"
37 #include "qemu/error-report.h"
38 #include "qemu/config-file.h"
39 #include "qemu/bswap.h"
41 #include "qemu/systemd.h"
42 #include "qapi/util.h"
43 #include "qapi/qmp/qstring.h"
44 #include "io/channel-socket.h"
45 #include "trace/control.h"
46 #include "qemu-version.h"
48 #include "block/aio.h"
49 #include "block/thread-pool.h"
51 #include "scsi/constants.h"
52 #include "scsi/utils.h"
53 #include "pr-helper.h"
55 #define PR_OUT_FIXED_PARAM_SIZE 24
57 static char *socket_path
;
59 static enum { RUNNING
, TERMINATE
, TERMINATING
} state
;
60 static QIOChannelSocket
*server_ioc
;
61 static int server_watch
;
62 static int num_active_sockets
= 1;
70 static void usage(const char *name
)
73 "Usage: %s [OPTIONS] FILE\n"
74 "Persistent Reservation helper program for QEMU\n"
76 " -h, --help display this help and exit\n"
77 " -V, --version output version information and exit\n"
79 " -d, --daemon run in the background\n"
80 " -f, --pidfile=PATH PID file when running as a daemon\n"
82 " -k, --socket=PATH path to the unix socket\n"
84 " -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
85 " specify tracing options\n"
87 " -u, --user=USER user to drop privileges to\n"
88 " -g, --group=GROUP group to drop privileges to\n"
92 , name
, pidfile
, socket_path
);
95 static void version(const char *name
)
98 "%s " QEMU_VERSION QEMU_PKGVERSION
"\n"
99 "Written by Paolo Bonzini.\n"
102 "This is free software; see the source for copying conditions. There is NO\n"
103 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
107 static void write_pidfile(void)
112 pidfd
= qemu_open(pidfile
, O_CREAT
|O_WRONLY
, S_IRUSR
|S_IWUSR
);
114 error_report("Cannot open pid file, %s", strerror(errno
));
118 if (lockf(pidfd
, F_TLOCK
, 0)) {
119 error_report("Cannot lock pid file, %s", strerror(errno
));
122 if (ftruncate(pidfd
, 0)) {
123 error_report("Failed to truncate pid file");
127 snprintf(pidstr
, sizeof(pidstr
), "%d\n", getpid());
128 if (write(pidfd
, pidstr
, strlen(pidstr
)) != strlen(pidstr
)) {
129 error_report("Failed to write pid file");
142 typedef struct PRHelperSGIOData
{
147 int sz
; /* input/output */
151 static int do_sgio_worker(void *opaque
)
153 PRHelperSGIOData
*data
= opaque
;
154 struct sg_io_hdr io_hdr
;
157 SCSISense sense_code
;
159 memset(data
->sense
, 0, PR_HELPER_SENSE_SIZE
);
160 memset(&io_hdr
, 0, sizeof(io_hdr
));
161 io_hdr
.interface_id
= 'S';
162 io_hdr
.cmd_len
= PR_HELPER_CDB_SIZE
;
163 io_hdr
.cmdp
= (uint8_t *)data
->cdb
;
164 io_hdr
.sbp
= data
->sense
;
165 io_hdr
.mx_sb_len
= PR_HELPER_SENSE_SIZE
;
167 io_hdr
.dxfer_direction
= data
->dir
;
168 io_hdr
.dxferp
= (char *)data
->buf
;
169 io_hdr
.dxfer_len
= data
->sz
;
170 ret
= ioctl(data
->fd
, SG_IO
, &io_hdr
);
171 status
= sg_io_sense_from_errno(ret
< 0 ? errno
: 0, &io_hdr
,
173 if (status
== GOOD
) {
174 data
->sz
-= io_hdr
.resid
;
179 if (status
== CHECK_CONDITION
&&
180 !(io_hdr
.driver_status
& SG_ERR_DRIVER_SENSE
)) {
181 scsi_build_sense(data
->sense
, sense_code
);
187 static int do_sgio(int fd
, const uint8_t *cdb
, uint8_t *sense
,
188 uint8_t *buf
, int *sz
, int dir
)
190 ThreadPool
*pool
= aio_get_thread_pool(qemu_get_aio_context());
193 PRHelperSGIOData data
= {
202 r
= thread_pool_submit_co(pool
, do_sgio_worker
, &data
);
207 static int do_pr_in(int fd
, const uint8_t *cdb
, uint8_t *sense
,
208 uint8_t *data
, int *resp_sz
)
210 return do_sgio(fd
, cdb
, sense
, data
, resp_sz
,
214 static int do_pr_out(int fd
, const uint8_t *cdb
, uint8_t *sense
,
215 const uint8_t *param
, int sz
)
218 return do_sgio(fd
, cdb
, sense
, (uint8_t *)param
, &resp_sz
,
224 typedef struct PRHelperClient
{
225 QIOChannelSocket
*ioc
;
228 uint8_t data
[PR_HELPER_DATA_SIZE
];
231 typedef struct PRHelperRequest
{
234 uint8_t cdb
[PR_HELPER_CDB_SIZE
];
237 static int coroutine_fn
prh_read(PRHelperClient
*client
, void *buf
, int sz
,
251 n_read
= qio_channel_readv_full(QIO_CHANNEL(client
->ioc
), &iov
, 1,
254 if (n_read
== QIO_CHANNEL_ERR_BLOCK
) {
255 qio_channel_yield(QIO_CHANNEL(client
->ioc
), G_IO_IN
);
259 ret
= n_read
? n_read
: -1;
263 /* Stash one file descriptor per request. */
265 bool too_many
= false;
266 for (i
= 0; i
< nfds
; i
++) {
267 if (client
->fd
== -1) {
288 if (client
->fd
!= -1) {
295 static int coroutine_fn
prh_read_request(PRHelperClient
*client
,
296 PRHelperRequest
*req
,
297 PRHelperResponse
*resp
, Error
**errp
)
301 if (prh_read(client
, req
->cdb
, sizeof(req
->cdb
), NULL
) < 0) {
305 if (client
->fd
== -1) {
306 error_setg(errp
, "No file descriptor in request.");
310 if (req
->cdb
[0] != PERSISTENT_RESERVE_OUT
&&
311 req
->cdb
[0] != PERSISTENT_RESERVE_IN
) {
312 error_setg(errp
, "Invalid CDB, closing socket.");
316 sz
= scsi_cdb_xfer(req
->cdb
);
317 if (sz
> sizeof(client
->data
)) {
321 if (req
->cdb
[0] == PERSISTENT_RESERVE_OUT
) {
322 if (qio_channel_read_all(QIO_CHANNEL(client
->ioc
),
323 (char *)client
->data
, sz
,
327 if ((fcntl(client
->fd
, F_GETFL
) & O_ACCMODE
) == O_RDONLY
) {
328 scsi_build_sense(resp
->sense
, SENSE_CODE(INVALID_OPCODE
));
330 } else if (sz
< PR_OUT_FIXED_PARAM_SIZE
) {
331 /* Illegal request, Parameter list length error. This isn't fatal;
332 * we have read the data, send an error without closing the socket.
334 scsi_build_sense(resp
->sense
, SENSE_CODE(INVALID_PARAM_LEN
));
338 resp
->result
= CHECK_CONDITION
;
344 req
->fd
= client
->fd
;
355 static int coroutine_fn
prh_write_response(PRHelperClient
*client
,
356 PRHelperRequest
*req
,
357 PRHelperResponse
*resp
, Error
**errp
)
362 if (req
->cdb
[0] == PERSISTENT_RESERVE_IN
&& resp
->result
== GOOD
) {
363 assert(resp
->sz
<= req
->sz
&& resp
->sz
<= sizeof(client
->data
));
365 assert(resp
->sz
== 0);
370 resp
->result
= cpu_to_be32(resp
->result
);
371 resp
->sz
= cpu_to_be32(resp
->sz
);
372 r
= qio_channel_write_all(QIO_CHANNEL(client
->ioc
),
373 (char *) resp
, sizeof(*resp
), errp
);
378 r
= qio_channel_write_all(QIO_CHANNEL(client
->ioc
),
379 (char *) client
->data
,
381 return r
< 0 ? r
: 0;
384 static void coroutine_fn
prh_co_entry(void *opaque
)
386 PRHelperClient
*client
= opaque
;
387 Error
*local_err
= NULL
;
391 qio_channel_set_blocking(QIO_CHANNEL(client
->ioc
),
393 qio_channel_attach_aio_context(QIO_CHANNEL(client
->ioc
),
394 qemu_get_aio_context());
396 /* A very simple negotiation for future extensibility. No features
397 * are defined so write 0.
399 flags
= cpu_to_be32(0);
400 r
= qio_channel_write_all(QIO_CHANNEL(client
->ioc
),
401 (char *) &flags
, sizeof(flags
), NULL
);
406 r
= qio_channel_read_all(QIO_CHANNEL(client
->ioc
),
407 (char *) &flags
, sizeof(flags
), NULL
);
408 if (be32_to_cpu(flags
) != 0 || r
< 0) {
412 while (atomic_read(&state
) == RUNNING
) {
414 PRHelperResponse resp
;
417 sz
= prh_read_request(client
, &req
, &resp
, &local_err
);
423 num_active_sockets
++;
424 if (req
.cdb
[0] == PERSISTENT_RESERVE_OUT
) {
425 r
= do_pr_out(req
.fd
, req
.cdb
, resp
.sense
,
429 resp
.sz
= sizeof(client
->data
);
430 r
= do_pr_in(req
.fd
, req
.cdb
, resp
.sense
,
431 client
->data
, &resp
.sz
);
432 resp
.sz
= MIN(resp
.sz
, sz
);
434 num_active_sockets
--;
442 if (prh_write_response(client
, &req
, &resp
, &local_err
) < 0) {
449 error_free(local_err
);
451 error_report_err(local_err
);
456 qio_channel_detach_aio_context(QIO_CHANNEL(client
->ioc
));
457 object_unref(OBJECT(client
->ioc
));
461 static gboolean
accept_client(QIOChannel
*ioc
, GIOCondition cond
, gpointer opaque
)
463 QIOChannelSocket
*cioc
;
466 cioc
= qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc
),
472 prh
= g_new(PRHelperClient
, 1);
475 prh
->co
= qemu_coroutine_create(prh_co_entry
, prh
);
476 qemu_coroutine_enter(prh
->co
);
483 * Check socket parameters compatibility when socket activation is used.
485 static const char *socket_activation_validate_opts(void)
487 if (socket_path
!= NULL
) {
488 return "Unix socket can't be set when using socket activation";
494 static void compute_default_paths(void)
497 socket_path
= qemu_get_local_state_pathname("run/qemu-pr-helper.sock");
501 static void termsig_handler(int signum
)
503 atomic_cmpxchg(&state
, RUNNING
, TERMINATE
);
507 static void close_server_socket(void)
511 g_source_remove(server_watch
);
513 object_unref(OBJECT(server_ioc
));
514 num_active_sockets
--;
518 static int drop_privileges(void)
520 /* clear all capabilities */
521 capng_clear(CAPNG_SELECT_BOTH
);
523 if (capng_update(CAPNG_ADD
, CAPNG_EFFECTIVE
| CAPNG_PERMITTED
,
524 CAP_SYS_RAWIO
) < 0) {
528 /* Change user/group id, retaining the capabilities. Because file descriptors
529 * are passed via SCM_RIGHTS, we don't need supplementary groups (and in
530 * fact the helper can run as "nobody").
532 if (capng_change_id(uid
!= -1 ? uid
: getuid(),
533 gid
!= -1 ? gid
: getgid(),
534 CAPNG_DROP_SUPP_GRP
| CAPNG_CLEAR_BOUNDING
)) {
542 int main(int argc
, char **argv
)
544 const char *sopt
= "hVk:fdT:u:g:q";
545 struct option lopt
[] = {
546 { "help", no_argument
, NULL
, 'h' },
547 { "version", no_argument
, NULL
, 'V' },
548 { "socket", required_argument
, NULL
, 'k' },
549 { "pidfile", no_argument
, NULL
, 'f' },
550 { "daemon", no_argument
, NULL
, 'd' },
551 { "trace", required_argument
, NULL
, 'T' },
552 { "user", required_argument
, NULL
, 'u' },
553 { "group", required_argument
, NULL
, 'g' },
554 { "quiet", no_argument
, NULL
, 'q' },
560 Error
*local_err
= NULL
;
561 char *trace_file
= NULL
;
562 bool daemonize
= false;
563 unsigned socket_activation
;
565 struct sigaction sa_sigterm
;
566 memset(&sa_sigterm
, 0, sizeof(sa_sigterm
));
567 sa_sigterm
.sa_handler
= termsig_handler
;
568 sigaction(SIGTERM
, &sa_sigterm
, NULL
);
569 sigaction(SIGINT
, &sa_sigterm
, NULL
);
570 sigaction(SIGHUP
, &sa_sigterm
, NULL
);
572 signal(SIGPIPE
, SIG_IGN
);
574 module_call_init(MODULE_INIT_TRACE
);
575 module_call_init(MODULE_INIT_QOM
);
576 qemu_add_opts(&qemu_trace_opts
);
577 qemu_init_exec_dir(argv
[0]);
579 pidfile
= qemu_get_local_state_pathname("run/qemu-pr-helper.pid");
581 while ((ch
= getopt_long(argc
, argv
, sopt
, lopt
, &opt_ind
)) != -1) {
584 socket_path
= optarg
;
585 if (socket_path
[0] != '/') {
586 error_report("socket path must be absolute");
596 struct passwd
*userinfo
= getpwnam(optarg
);
598 uid
= userinfo
->pw_uid
;
599 } else if (qemu_strtoul(optarg
, NULL
, 10, &res
) == 0 &&
603 error_report("invalid user '%s'", optarg
);
610 struct group
*groupinfo
= getgrnam(optarg
);
612 gid
= groupinfo
->gr_gid
;
613 } else if (qemu_strtoul(optarg
, NULL
, 10, &res
) == 0 &&
617 error_report("invalid group '%s'", optarg
);
625 error_report("-%c not supported by this %s", ch
, argv
[0]);
636 trace_file
= trace_opt_parse(optarg
);
647 error_report("Try `%s --help' for more information.", argv
[0]);
655 if (!trace_init_backends()) {
658 trace_init_file(trace_file
);
659 qemu_set_log(LOG_TRACE
);
661 socket_activation
= check_socket_activation();
662 if (socket_activation
== 0) {
664 compute_default_paths();
665 saddr
= (SocketAddress
){
666 .type
= SOCKET_ADDRESS_TYPE_UNIX
,
667 .u
.q_unix
.path
= g_strdup(socket_path
)
669 server_ioc
= qio_channel_socket_new();
670 if (qio_channel_socket_listen_sync(server_ioc
, &saddr
, &local_err
) < 0) {
671 object_unref(OBJECT(server_ioc
));
672 error_report_err(local_err
);
675 g_free(saddr
.u
.q_unix
.path
);
677 /* Using socket activation - check user didn't use -p etc. */
678 const char *err_msg
= socket_activation_validate_opts();
679 if (err_msg
!= NULL
) {
680 error_report("%s", err_msg
);
684 /* Can only listen on a single socket. */
685 if (socket_activation
> 1) {
686 error_report("%s does not support socket activation with LISTEN_FDS > 1",
690 server_ioc
= qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD
,
692 if (server_ioc
== NULL
) {
693 error_report("Failed to use socket activation: %s",
694 error_get_pretty(local_err
));
700 if (qemu_init_main_loop(&local_err
)) {
701 error_report_err(local_err
);
705 server_watch
= qio_channel_add_watch(QIO_CHANNEL(server_ioc
),
711 if (drop_privileges() < 0) {
712 error_report("Failed to drop privileges: %s", strerror(errno
));
718 if (daemon(0, 0) < 0) {
719 error_report("Failed to daemonize: %s", strerror(errno
));
727 main_loop_wait(false);
728 if (state
== TERMINATE
) {
730 close_server_socket();
732 } while (num_active_sockets
> 0);