security_stack.c 15.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (C) 2010-2011 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library.  If not, see
O
Osier Yang 已提交
16
 * <http://www.gnu.org/licenses/>.
17 18 19 20 21 22 23 24 25
 *
 * Stacked security driver
 */

#include <config.h>

#include "security_stack.h"

#include "virterror_internal.h"
26
#include "viralloc.h"
27 28 29 30 31

#define VIR_FROM_THIS VIR_FROM_SECURITY

typedef struct _virSecurityStackData virSecurityStackData;
typedef virSecurityStackData *virSecurityStackDataPtr;
32 33 34 35 36 37 38
typedef struct _virSecurityStackItem virSecurityStackItem;
typedef virSecurityStackItem* virSecurityStackItemPtr;

struct _virSecurityStackItem {
    virSecurityManagerPtr securityManager;
    virSecurityStackItemPtr next;
};
39 40

struct _virSecurityStackData {
41
    virSecurityStackItemPtr itemsHead;
42 43
};

44 45 46 47 48 49
int
virSecurityStackAddNested(virSecurityManagerPtr mgr,
                          virSecurityManagerPtr nested)
{
    virSecurityStackItemPtr item = NULL;
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
50 51 52 53 54
    virSecurityStackItemPtr tmp;

    tmp = priv->itemsHead;
    while (tmp && tmp->next)
        tmp = tmp->next;
55 56 57 58 59 60

    if (VIR_ALLOC(item) < 0) {
        virReportOOMError();
        return -1;
    }
    item->securityManager = nested;
61 62 63 64 65
    if (tmp)
        tmp->next = item;
    else
        priv->itemsHead = item;

66 67 68 69 70 71 72
    return 0;
}

virSecurityManagerPtr
virSecurityStackGetPrimary(virSecurityManagerPtr mgr)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
73
    return priv->itemsHead->securityManager;
74 75 76
}

static virSecurityDriverStatus
77
virSecurityStackProbe(const char *virtDriver ATTRIBUTE_UNUSED)
78 79 80 81 82 83 84 85 86 87 88
{
    return SECURITY_DRIVER_ENABLE;
}

static int
virSecurityStackOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
E
Eric Blake 已提交
89
virSecurityStackClose(virSecurityManagerPtr mgr)
90
{
E
Eric Blake 已提交
91
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
92
    virSecurityStackItemPtr next, item = priv->itemsHead;
E
Eric Blake 已提交
93

94 95 96 97 98 99
    while (item) {
        next = item->next;
        virSecurityManagerFree(item->securityManager);
        VIR_FREE(item);
        item = next;
    }
E
Eric Blake 已提交
100

101 102 103 104 105 106
    return 0;
}

static const char *
virSecurityStackGetModel(virSecurityManagerPtr mgr)
{
107
    return virSecurityManagerGetModel(virSecurityStackGetPrimary(mgr));
108 109 110 111 112
}

static const char *
virSecurityStackGetDOI(virSecurityManagerPtr mgr)
{
113
    return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
114 115 116 117 118 119 120
}

static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
121
    virSecurityStackItemPtr item = priv->itemsHead;
122 123
    int rc = 0;

124
    for (; item; item = item->next) {
125 126 127 128 129
        if (virSecurityManagerVerify(item->securityManager, def) < 0) {
            rc = -1;
            break;
        }
    }
130 131 132 133 134 135 136

    return rc;
}


static int
virSecurityStackGenLabel(virSecurityManagerPtr mgr,
137
                         virDomainDefPtr vm)
138 139 140
{
    int rc = 0;

141
    if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
142 143
        rc = -1;

144
// TODO
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
#if 0
    /* We don't allow secondary drivers to generate labels.
     * This may have to change in the future, but requires
     * changes elsewhere in domain_conf.c and capabilities.c
     * XML formats first, to allow recording of multiple
     * labels
     */
    if (virSecurityManagerGenLabel(priv->secondary, vm) < 0)
        rc = -1;
#endif

    return rc;
}


static int
virSecurityStackReleaseLabel(virSecurityManagerPtr mgr,
162
                             virDomainDefPtr vm)
163 164 165
{
    int rc = 0;

166
    if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
167
        rc = -1;
168 169

// TODO
170 171 172 173 174 175 176 177 178 179 180 181
#if 0
    /* XXX See note in GenLabel */
    if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
        rc = -1;
#endif

    return rc;
}


static int
virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
182 183
                             virDomainDefPtr vm,
                             pid_t pid)
184 185 186
{
    int rc = 0;

187
    if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
188
        rc = -1;
189
// TODO
190 191
#if 0
    /* XXX See note in GenLabel */
192
    if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
193 194 195 196 197 198 199 200 201
        rc = -1;
#endif

    return rc;
}


static int
virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
202
                                      virDomainDefPtr vm,
203 204 205
                                      virDomainDiskDefPtr disk)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
206
    virSecurityStackItemPtr item = priv->itemsHead;
207 208
    int rc = 0;

209 210 211 212
    for (; item; item = item->next) {
        if (virSecurityManagerSetImageLabel(item->securityManager, vm, disk) < 0)
            rc = -1;
    }
213 214 215 216 217 218 219

    return rc;
}


static int
virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
220
                                          virDomainDefPtr vm,
221 222 223
                                          virDomainDiskDefPtr disk)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
224
    virSecurityStackItemPtr item = priv->itemsHead;
225 226
    int rc = 0;

227 228 229 230
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreImageLabel(item->securityManager, vm, disk) < 0)
            rc = -1;
    }
231 232 233 234 235 236 237

    return rc;
}


static int
virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
238
                                        virDomainDefPtr vm,
239 240
                                        virDomainHostdevDefPtr dev,
                                        const char *vroot)
241 242 243

{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
244
    virSecurityStackItemPtr item = priv->itemsHead;
245 246
    int rc = 0;

247
    for (; item; item = item->next) {
248 249 250 251
        if (virSecurityManagerSetHostdevLabel(item->securityManager,
                                              vm,
                                              dev,
                                              vroot) < 0)
252 253
            rc = -1;
    }
254 255 256 257 258 259 260

    return rc;
}


static int
virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
261
                                            virDomainDefPtr vm,
262 263
                                            virDomainHostdevDefPtr dev,
                                            const char *vroot)
264 265
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
266
    virSecurityStackItemPtr item = priv->itemsHead;
267 268
    int rc = 0;

269
    for (; item; item = item->next) {
270 271 272 273
        if (virSecurityManagerRestoreHostdevLabel(item->securityManager,
                                                  vm,
                                                  dev,
                                                  vroot) < 0)
274 275
            rc = -1;
    }
276 277 278 279 280 281 282

    return rc;
}


static int
virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
283
                                    virDomainDefPtr vm,
284 285 286
                                    const char *stdin_path)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
287
    virSecurityStackItemPtr item = priv->itemsHead;
288 289
    int rc = 0;

290 291 292 293
    for (; item; item = item->next) {
        if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
            rc = -1;
    }
294 295 296 297 298 299 300

    return rc;
}


static int
virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
301
                                        virDomainDefPtr vm,
302 303 304
                                        int migrated)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
305
    virSecurityStackItemPtr item = priv->itemsHead;
306 307
    int rc = 0;

308 309 310 311
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
            rc = -1;
    }
312 313 314 315 316 317 318

    return rc;
}


static int
virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
319
                                   virDomainDefPtr vm,
320 321 322
                                   const char *savefile)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
323
    virSecurityStackItemPtr item = priv->itemsHead;
324 325
    int rc = 0;

326 327 328 329
    for (; item; item = item->next) {
        if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
            rc = -1;
    }
330 331 332 333 334 335 336

    return rc;
}


static int
virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
337
                                       virDomainDefPtr vm,
338 339 340
                                       const char *savefile)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
341
    virSecurityStackItemPtr item = priv->itemsHead;
342 343
    int rc = 0;

344 345 346 347
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreSavedStateLabel(item->securityManager, vm, savefile) < 0)
            rc = -1;
    }
348 349 350 351 352 353 354

    return rc;
}


static int
virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
355
                                virDomainDefPtr vm)
356 357
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
358
    virSecurityStackItemPtr item = priv->itemsHead;
359 360
    int rc = 0;

361 362 363 364
    for (; item; item = item->next) {
        if (virSecurityManagerSetProcessLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
365 366 367 368 369 370

    return rc;
}

static int
virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
371 372
                                virDomainDefPtr vm,
                                pid_t pid,
373 374 375 376
                                virSecurityLabelPtr seclabel)
{
    int rc = 0;

377
// TODO
378
#if 0
379
    if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
380 381
        rc = -1;
#endif
382
    if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
383 384 385 386 387 388 389
        rc = -1;

    return rc;
}


static int
390
virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
391
                                     virDomainDefPtr vm)
392 393
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
394
    virSecurityStackItemPtr item = priv->itemsHead;
395 396
    int rc = 0;

397 398 399 400
    for (; item; item = item->next) {
        if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
401 402 403 404 405

    return rc;
}


406 407
static int
virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
408
                               virDomainDefPtr vm)
409 410
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
411
    virSecurityStackItemPtr item = priv->itemsHead;
412 413
    int rc = 0;

414 415 416 417
    for (; item; item = item->next) {
        if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
418 419 420 421 422

    return rc;
}


423 424
static int
virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
425
                                 virDomainDefPtr vm)
426 427
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
428
    virSecurityStackItemPtr item = priv->itemsHead;
429 430
    int rc = 0;

431 432 433 434
    for (; item; item = item->next) {
        if (virSecurityManagerClearSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
435 436 437 438

    return rc;
}

439
static int
440
virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
441
                                virDomainDefPtr vm,
442
                                int fd)
443 444
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
445
    virSecurityStackItemPtr item = priv->itemsHead;
446 447
    int rc = 0;

448 449 450 451
    for (; item; item = item->next) {
        if (virSecurityManagerSetImageFDLabel(item->securityManager, vm, fd) < 0)
            rc = -1;
    }
452 453 454 455

    return rc;
}

456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
static int
virSecurityStackSetTapFDLabel(virSecurityManagerPtr mgr,
                              virDomainDefPtr vm,
                              int fd)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

    for (; item; item = item->next) {
        if (virSecurityManagerSetTapFDLabel(item->securityManager, vm, fd) < 0)
            rc = -1;
    }

    return rc;
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
static int
virSecurityStackSetHugepages(virSecurityManagerPtr mgr,
                              virDomainDefPtr vm,
                              const char *path)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

    for (; item; item = item->next) {
        if (virSecurityManagerSetHugepages(item->securityManager, vm, path) < 0)
            rc = -1;
    }

    return rc;
}

490 491 492 493
static char *virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                             virDomainDefPtr vm ATTRIBUTE_UNUSED) {
    return NULL;
}
494

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
virSecurityManagerPtr*
virSecurityStackGetNested(virSecurityManagerPtr mgr)
{
    virSecurityManagerPtr *list = NULL;
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item;
    int len = 0, i = 0;

    for (item = priv->itemsHead; item; item = item->next)
        len++;

    if (VIR_ALLOC_N(list, len + 1) < 0) {
        virReportOOMError();
        return NULL;
    }

    for (item = priv->itemsHead; item; item = item->next, i++)
        list[i] = item->securityManager;
    list[len] = NULL;

    return list;
}

518
virSecurityDriver virSecurityDriverStack = {
519 520 521 522 523
    .privateDataLen                     = sizeof(virSecurityStackData),
    .name                               = "stack",
    .probe                              = virSecurityStackProbe,
    .open                               = virSecurityStackOpen,
    .close                              = virSecurityStackClose,
524

525 526
    .getModel                           = virSecurityStackGetModel,
    .getDOI                             = virSecurityStackGetDOI,
527

528
    .domainSecurityVerify               = virSecurityStackVerify,
529

530 531
    .domainSetSecurityImageLabel        = virSecurityStackSetSecurityImageLabel,
    .domainRestoreSecurityImageLabel    = virSecurityStackRestoreSecurityImageLabel,
532

533 534 535
    .domainSetSecurityDaemonSocketLabel = virSecurityStackSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityStackSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityStackClearSocketLabel,
536

537 538 539
    .domainGenSecurityLabel             = virSecurityStackGenLabel,
    .domainReserveSecurityLabel         = virSecurityStackReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityStackReleaseLabel,
540

541 542
    .domainGetSecurityProcessLabel      = virSecurityStackGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityStackSetProcessLabel,
543

544 545
    .domainSetSecurityAllLabel          = virSecurityStackSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityStackRestoreSecurityAllLabel,
546

547 548
    .domainSetSecurityHostdevLabel      = virSecurityStackSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityStackRestoreSecurityHostdevLabel,
549

550 551
    .domainSetSavedStateLabel           = virSecurityStackSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityStackRestoreSavedStateLabel,
552

553
    .domainSetSecurityImageFDLabel      = virSecurityStackSetImageFDLabel,
554
    .domainSetSecurityTapFDLabel        = virSecurityStackSetTapFDLabel,
555

556
    .domainGetSecurityMountOptions      = virSecurityStackGetMountOptions,
557 558

    .domainSetSecurityHugepages         = virSecurityStackSetHugepages,
559
};