qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

sandbox: disable -sandbox if CONFIG_SECCOMP undefined

If CONFIG_SECCOMP is undefined, the option 'elevatedprivileges' remains
compiled. This would make libvirt set the corresponding capability and
then trigger failure during guest startup. This patch moves the code
regarding seccomp command line options to qemu-seccomp.c file and
wraps qemu_opts_foreach finding sandbox option with CONFIG_SECCOMP.
Because parse_sandbox() is moved into qemu-seccomp.c file, change
seccomp_start() to static function.

Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Tested-by: Ján Tomko <jtomko@redhat.com>
Acked-by: Eduardo Otubo <otubo@redhat.com>

authored by

Yi Min Zhao and committed by
Eduardo Otubo
9d0fdecb 14fc6184

+130 -118
+2 -1
include/sysemu/seccomp.h
··· 21 21 #define QEMU_SECCOMP_SET_SPAWN (1 << 3) 22 22 #define QEMU_SECCOMP_SET_RESOURCECTL (1 << 4) 23 23 24 - int seccomp_start(uint32_t seccomp_opts); 24 + int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp); 25 + 25 26 #endif
+120 -1
qemu-seccomp.c
··· 13 13 * GNU GPL, version 2 or (at your option) any later version. 14 14 */ 15 15 #include "qemu/osdep.h" 16 + #include "qemu/config-file.h" 17 + #include "qemu/option.h" 18 + #include "qemu/module.h" 19 + #include "qemu/error-report.h" 20 + #include <sys/prctl.h> 16 21 #include <seccomp.h> 17 22 #include "sysemu/seccomp.h" 18 23 ··· 96 101 }; 97 102 98 103 99 - int seccomp_start(uint32_t seccomp_opts) 104 + static int seccomp_start(uint32_t seccomp_opts) 100 105 { 101 106 int rc = 0; 102 107 unsigned int i = 0; ··· 125 130 seccomp_release(ctx); 126 131 return rc; 127 132 } 133 + 134 + #ifdef CONFIG_SECCOMP 135 + int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp) 136 + { 137 + if (qemu_opt_get_bool(opts, "enable", false)) { 138 + uint32_t seccomp_opts = QEMU_SECCOMP_SET_DEFAULT 139 + | QEMU_SECCOMP_SET_OBSOLETE; 140 + const char *value = NULL; 141 + 142 + value = qemu_opt_get(opts, "obsolete"); 143 + if (value) { 144 + if (g_str_equal(value, "allow")) { 145 + seccomp_opts &= ~QEMU_SECCOMP_SET_OBSOLETE; 146 + } else if (g_str_equal(value, "deny")) { 147 + /* this is the default option, this if is here 148 + * to provide a little bit of consistency for 149 + * the command line */ 150 + } else { 151 + error_report("invalid argument for obsolete"); 152 + return -1; 153 + } 154 + } 155 + 156 + value = qemu_opt_get(opts, "elevateprivileges"); 157 + if (value) { 158 + if (g_str_equal(value, "deny")) { 159 + seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED; 160 + } else if (g_str_equal(value, "children")) { 161 + seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED; 162 + 163 + /* calling prctl directly because we're 164 + * not sure if host has CAP_SYS_ADMIN set*/ 165 + if (prctl(PR_SET_NO_NEW_PRIVS, 1)) { 166 + error_report("failed to set no_new_privs " 167 + "aborting"); 168 + return -1; 169 + } 170 + } else if (g_str_equal(value, "allow")) { 171 + /* default value */ 172 + } else { 173 + error_report("invalid argument for elevateprivileges"); 174 + return -1; 175 + } 176 + } 177 + 178 + value = qemu_opt_get(opts, "spawn"); 179 + if (value) { 180 + if (g_str_equal(value, "deny")) { 181 + seccomp_opts |= QEMU_SECCOMP_SET_SPAWN; 182 + } else if (g_str_equal(value, "allow")) { 183 + /* default value */ 184 + } else { 185 + error_report("invalid argument for spawn"); 186 + return -1; 187 + } 188 + } 189 + 190 + value = qemu_opt_get(opts, "resourcecontrol"); 191 + if (value) { 192 + if (g_str_equal(value, "deny")) { 193 + seccomp_opts |= QEMU_SECCOMP_SET_RESOURCECTL; 194 + } else if (g_str_equal(value, "allow")) { 195 + /* default value */ 196 + } else { 197 + error_report("invalid argument for resourcecontrol"); 198 + return -1; 199 + } 200 + } 201 + 202 + if (seccomp_start(seccomp_opts) < 0) { 203 + error_report("failed to install seccomp syscall filter " 204 + "in the kernel"); 205 + return -1; 206 + } 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static QemuOptsList qemu_sandbox_opts = { 213 + .name = "sandbox", 214 + .implied_opt_name = "enable", 215 + .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head), 216 + .desc = { 217 + { 218 + .name = "enable", 219 + .type = QEMU_OPT_BOOL, 220 + }, 221 + { 222 + .name = "obsolete", 223 + .type = QEMU_OPT_STRING, 224 + }, 225 + { 226 + .name = "elevateprivileges", 227 + .type = QEMU_OPT_STRING, 228 + }, 229 + { 230 + .name = "spawn", 231 + .type = QEMU_OPT_STRING, 232 + }, 233 + { 234 + .name = "resourcecontrol", 235 + .type = QEMU_OPT_STRING, 236 + }, 237 + { /* end of list */ } 238 + }, 239 + }; 240 + 241 + static void seccomp_register(void) 242 + { 243 + qemu_add_opts(&qemu_sandbox_opts); 244 + } 245 + opts_init(seccomp_register); 246 + #endif
+8 -116
vl.c
··· 28 28 #include "qemu/cutils.h" 29 29 #include "qemu/help_option.h" 30 30 #include "qemu/uuid.h" 31 - 32 - #ifdef CONFIG_SECCOMP 33 - #include <sys/prctl.h> 34 31 #include "sysemu/seccomp.h" 35 - #endif 36 32 37 33 #ifdef CONFIG_SDL 38 34 #if defined(__APPLE__) || defined(main) ··· 253 249 .type = QEMU_OPT_STRING, 254 250 },{ 255 251 .name = "driftfix", 256 - .type = QEMU_OPT_STRING, 257 - }, 258 - { /* end of list */ } 259 - }, 260 - }; 261 - 262 - static QemuOptsList qemu_sandbox_opts = { 263 - .name = "sandbox", 264 - .implied_opt_name = "enable", 265 - .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head), 266 - .desc = { 267 - { 268 - .name = "enable", 269 - .type = QEMU_OPT_BOOL, 270 - }, 271 - { 272 - .name = "obsolete", 273 - .type = QEMU_OPT_STRING, 274 - }, 275 - { 276 - .name = "elevateprivileges", 277 - .type = QEMU_OPT_STRING, 278 - }, 279 - { 280 - .name = "spawn", 281 - .type = QEMU_OPT_STRING, 282 - }, 283 - { 284 - .name = "resourcecontrol", 285 252 .type = QEMU_OPT_STRING, 286 253 }, 287 254 { /* end of list */ } ··· 1050 1017 return 1; 1051 1018 } 1052 1019 1053 - static int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp) 1054 - { 1055 - if (qemu_opt_get_bool(opts, "enable", false)) { 1056 - #ifdef CONFIG_SECCOMP 1057 - uint32_t seccomp_opts = QEMU_SECCOMP_SET_DEFAULT 1058 - | QEMU_SECCOMP_SET_OBSOLETE; 1059 - const char *value = NULL; 1060 - 1061 - value = qemu_opt_get(opts, "obsolete"); 1062 - if (value) { 1063 - if (g_str_equal(value, "allow")) { 1064 - seccomp_opts &= ~QEMU_SECCOMP_SET_OBSOLETE; 1065 - } else if (g_str_equal(value, "deny")) { 1066 - /* this is the default option, this if is here 1067 - * to provide a little bit of consistency for 1068 - * the command line */ 1069 - } else { 1070 - error_report("invalid argument for obsolete"); 1071 - return -1; 1072 - } 1073 - } 1074 - 1075 - value = qemu_opt_get(opts, "elevateprivileges"); 1076 - if (value) { 1077 - if (g_str_equal(value, "deny")) { 1078 - seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED; 1079 - } else if (g_str_equal(value, "children")) { 1080 - seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED; 1081 - 1082 - /* calling prctl directly because we're 1083 - * not sure if host has CAP_SYS_ADMIN set*/ 1084 - if (prctl(PR_SET_NO_NEW_PRIVS, 1)) { 1085 - error_report("failed to set no_new_privs " 1086 - "aborting"); 1087 - return -1; 1088 - } 1089 - } else if (g_str_equal(value, "allow")) { 1090 - /* default value */ 1091 - } else { 1092 - error_report("invalid argument for elevateprivileges"); 1093 - return -1; 1094 - } 1095 - } 1096 - 1097 - value = qemu_opt_get(opts, "spawn"); 1098 - if (value) { 1099 - if (g_str_equal(value, "deny")) { 1100 - seccomp_opts |= QEMU_SECCOMP_SET_SPAWN; 1101 - } else if (g_str_equal(value, "allow")) { 1102 - /* default value */ 1103 - } else { 1104 - error_report("invalid argument for spawn"); 1105 - return -1; 1106 - } 1107 - } 1108 - 1109 - value = qemu_opt_get(opts, "resourcecontrol"); 1110 - if (value) { 1111 - if (g_str_equal(value, "deny")) { 1112 - seccomp_opts |= QEMU_SECCOMP_SET_RESOURCECTL; 1113 - } else if (g_str_equal(value, "allow")) { 1114 - /* default value */ 1115 - } else { 1116 - error_report("invalid argument for resourcecontrol"); 1117 - return -1; 1118 - } 1119 - } 1120 - 1121 - if (seccomp_start(seccomp_opts) < 0) { 1122 - error_report("failed to install seccomp syscall filter " 1123 - "in the kernel"); 1124 - return -1; 1125 - } 1126 - #else 1127 - error_report("seccomp support is disabled"); 1128 - return -1; 1129 - #endif 1130 - } 1131 - 1132 - return 0; 1133 - } 1134 - 1135 1020 static int parse_name(void *opaque, QemuOpts *opts, Error **errp) 1136 1021 { 1137 1022 const char *proc_name; ··· 3079 2964 qemu_add_opts(&qemu_mem_opts); 3080 2965 qemu_add_opts(&qemu_smp_opts); 3081 2966 qemu_add_opts(&qemu_boot_opts); 3082 - qemu_add_opts(&qemu_sandbox_opts); 3083 2967 qemu_add_opts(&qemu_add_fd_opts); 3084 2968 qemu_add_opts(&qemu_object_opts); 3085 2969 qemu_add_opts(&qemu_tpmdev_opts); ··· 3980 3864 qtest_log = optarg; 3981 3865 break; 3982 3866 case QEMU_OPTION_sandbox: 3867 + #ifdef CONFIG_SECCOMP 3983 3868 opts = qemu_opts_parse_noisily(qemu_find_opts("sandbox"), 3984 3869 optarg, true); 3985 3870 if (!opts) { 3986 3871 exit(1); 3987 3872 } 3873 + #else 3874 + error_report("-sandbox support is not enabled " 3875 + "in this QEMU binary"); 3876 + exit(1); 3877 + #endif 3988 3878 break; 3989 3879 case QEMU_OPTION_add_fd: 3990 3880 #ifndef _WIN32 ··· 4077 3967 exit(1); 4078 3968 } 4079 3969 3970 + #ifdef CONFIG_SECCOMP 4080 3971 if (qemu_opts_foreach(qemu_find_opts("sandbox"), 4081 3972 parse_sandbox, NULL, NULL)) { 4082 3973 exit(1); 4083 3974 } 3975 + #endif 4084 3976 4085 3977 if (qemu_opts_foreach(qemu_find_opts("name"), 4086 3978 parse_name, NULL, NULL)) {