security_stack.c 18.5 KB
Newer Older
1
/*
2
 * Copyright (C) 2010-2014 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * 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
 *
 * Stacked security driver
 */

#include <config.h>

#include "security_stack.h"

25
#include "virerror.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
typedef struct _virSecurityStackItem virSecurityStackItem;
33
typedef virSecurityStackItem *virSecurityStackItemPtr;
34 35 36 37 38

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
    if (VIR_ALLOC(item) < 0)
57 58
        return -1;
    item->securityManager = nested;
59 60 61 62 63
    if (tmp)
        tmp->next = item;
    else
        priv->itemsHead = item;

64 65 66 67 68 69 70
    return 0;
}

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

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

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

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

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

99 100 101 102 103 104
    return 0;
}

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

static const char *
virSecurityStackGetDOI(virSecurityManagerPtr mgr)
{
111
    return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
112 113
}

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
static int
virSecurityStackPreFork(virSecurityManagerPtr mgr)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

    /* XXX For now, we rely on no driver having any state that requires
     * rollback if a later driver in the stack fails; if this changes,
     * we'd need to split this into transaction semantics by dividing
     * the work into prepare/commit/abort.  */
    for (; item; item = item->next) {
        if (virSecurityManagerPreFork(item->securityManager) < 0) {
            rc = -1;
            break;
        }
E
Eric Blake 已提交
130 131 132 133 134
        /* Undo the unbalanced locking left behind after recursion; if
         * PostFork ever delegates to driver callbacks, we'd instead
         * need to recurse to an internal method that does not regrab
         * a lock. */
        virSecurityManagerPostFork(item->securityManager);
135 136 137 138 139
    }

    return rc;
}

140 141 142 143 144
static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
145
    virSecurityStackItemPtr item = priv->itemsHead;
146 147
    int rc = 0;

148
    for (; item; item = item->next) {
149 150 151 152 153
        if (virSecurityManagerVerify(item->securityManager, def) < 0) {
            rc = -1;
            break;
        }
    }
154 155 156 157 158 159 160

    return rc;
}


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

165
    if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
166 167
        rc = -1;

168
// TODO
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
#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,
186
                             virDomainDefPtr vm)
187 188 189
{
    int rc = 0;

190
    if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
191
        rc = -1;
192 193

// TODO
194 195 196 197 198 199 200 201 202 203 204 205
#if 0
    /* XXX See note in GenLabel */
    if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
        rc = -1;
#endif

    return rc;
}


static int
virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
206 207
                             virDomainDefPtr vm,
                             pid_t pid)
208 209 210
{
    int rc = 0;

211
    if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
212
        rc = -1;
213
// TODO
214 215
#if 0
    /* XXX See note in GenLabel */
216
    if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
217 218 219 220 221 222 223 224
        rc = -1;
#endif

    return rc;
}


static int
225 226 227
virSecurityStackSetSecurityDiskLabel(virSecurityManagerPtr mgr,
                                     virDomainDefPtr vm,
                                     virDomainDiskDefPtr disk)
228 229
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
230
    virSecurityStackItemPtr item = priv->itemsHead;
231 232
    int rc = 0;

233
    for (; item; item = item->next) {
234
        if (virSecurityManagerSetDiskLabel(item->securityManager, vm, disk) < 0)
235 236
            rc = -1;
    }
237 238 239 240 241 242

    return rc;
}


static int
243 244 245
virSecurityStackRestoreSecurityDiskLabel(virSecurityManagerPtr mgr,
                                         virDomainDefPtr vm,
                                         virDomainDiskDefPtr disk)
246 247
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
248
    virSecurityStackItemPtr item = priv->itemsHead;
249 250
    int rc = 0;

251
    for (; item; item = item->next) {
252
        if (virSecurityManagerRestoreDiskLabel(item->securityManager, vm, disk) < 0)
253 254
            rc = -1;
    }
255 256 257 258 259 260 261

    return rc;
}


static int
virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
262
                                        virDomainDefPtr vm,
263 264
                                        virDomainHostdevDefPtr dev,
                                        const char *vroot)
265 266 267

{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
268
    virSecurityStackItemPtr item = priv->itemsHead;
269 270
    int rc = 0;

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

    return rc;
}


static int
virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
285
                                            virDomainDefPtr vm,
286 287
                                            virDomainHostdevDefPtr dev,
                                            const char *vroot)
288 289
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
290
    virSecurityStackItemPtr item = priv->itemsHead;
291 292
    int rc = 0;

293
    for (; item; item = item->next) {
294 295 296 297
        if (virSecurityManagerRestoreHostdevLabel(item->securityManager,
                                                  vm,
                                                  dev,
                                                  vroot) < 0)
298 299
            rc = -1;
    }
300 301 302 303 304 305 306

    return rc;
}


static int
virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
307
                                    virDomainDefPtr vm,
308 309 310
                                    const char *stdin_path)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
311
    virSecurityStackItemPtr item = priv->itemsHead;
312 313
    int rc = 0;

314 315 316 317
    for (; item; item = item->next) {
        if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
            rc = -1;
    }
318 319 320 321 322 323 324

    return rc;
}


static int
virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
325
                                        virDomainDefPtr vm,
326
                                        bool migrated)
327 328
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
329
    virSecurityStackItemPtr item = priv->itemsHead;
330 331
    int rc = 0;

332 333 334 335
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
            rc = -1;
    }
336 337 338 339 340 341 342

    return rc;
}


static int
virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
343
                                   virDomainDefPtr vm,
344 345 346
                                   const char *savefile)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
347
    virSecurityStackItemPtr item = priv->itemsHead;
348 349
    int rc = 0;

350 351 352 353
    for (; item; item = item->next) {
        if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
            rc = -1;
    }
354 355 356 357 358 359 360

    return rc;
}


static int
virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
361
                                       virDomainDefPtr vm,
362 363 364
                                       const char *savefile)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
365
    virSecurityStackItemPtr item = priv->itemsHead;
366 367
    int rc = 0;

368 369 370 371
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreSavedStateLabel(item->securityManager, vm, savefile) < 0)
            rc = -1;
    }
372 373 374 375 376 377 378

    return rc;
}


static int
virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
379
                                virDomainDefPtr vm)
380 381
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
382
    virSecurityStackItemPtr item = priv->itemsHead;
383 384
    int rc = 0;

385 386 387 388
    for (; item; item = item->next) {
        if (virSecurityManagerSetProcessLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
389 390 391 392

    return rc;
}

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
static int
virSecurityStackSetChildProcessLabel(virSecurityManagerPtr mgr,
                                     virDomainDefPtr vm,
                                     virCommandPtr cmd)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

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

    return rc;
}

410 411
static int
virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
412 413
                                virDomainDefPtr vm,
                                pid_t pid,
414 415 416 417
                                virSecurityLabelPtr seclabel)
{
    int rc = 0;

418
// TODO
419
#if 0
420
    if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
421 422
        rc = -1;
#endif
423
    if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
424 425 426 427 428 429 430
        rc = -1;

    return rc;
}


static int
431
virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
432
                                     virDomainDefPtr vm)
433 434
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
435
    virSecurityStackItemPtr item = priv->itemsHead;
436 437
    int rc = 0;

438 439 440 441
    for (; item; item = item->next) {
        if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
442 443 444 445 446

    return rc;
}


447 448
static int
virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
449
                               virDomainDefPtr vm)
450 451
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
452
    virSecurityStackItemPtr item = priv->itemsHead;
453 454
    int rc = 0;

455 456 457 458
    for (; item; item = item->next) {
        if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
459 460 461 462 463

    return rc;
}


464 465
static int
virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
466
                                 virDomainDefPtr vm)
467 468
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
469
    virSecurityStackItemPtr item = priv->itemsHead;
470 471
    int rc = 0;

472 473 474 475
    for (; item; item = item->next) {
        if (virSecurityManagerClearSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
476 477 478 479

    return rc;
}

480
static int
481
virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
482
                                virDomainDefPtr vm,
483
                                int fd)
484 485
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
486
    virSecurityStackItemPtr item = priv->itemsHead;
487 488
    int rc = 0;

489 490 491 492
    for (; item; item = item->next) {
        if (virSecurityManagerSetImageFDLabel(item->securityManager, vm, fd) < 0)
            rc = -1;
    }
493 494 495 496

    return rc;
}

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
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;
}

514 515
static int
virSecurityStackSetHugepages(virSecurityManagerPtr mgr,
516 517
                             virDomainDefPtr vm,
                             const char *path)
518 519 520 521 522 523 524 525 526 527 528 529 530
{
    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;
}

531 532 533 534
static char *
virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
535 536
    return NULL;
}
537

538 539 540 541 542 543
virSecurityManagerPtr*
virSecurityStackGetNested(virSecurityManagerPtr mgr)
{
    virSecurityManagerPtr *list = NULL;
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item;
544 545
    int len = 0;
    size_t i;
546 547 548 549

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

550
    if (VIR_ALLOC_N(list, len + 1) < 0)
551 552
        return NULL;

553
    for (i = 0, item = priv->itemsHead; item; item = item->next, i++)
554 555 556 557 558 559
        list[i] = item->securityManager;
    list[len] = NULL;

    return list;
}

560 561 562 563 564 565 566
static const char *
virSecurityStackGetBaseLabel(virSecurityManagerPtr mgr, int virtType)
{
    return virSecurityManagerGetBaseLabel(virSecurityStackGetPrimary(mgr),
                                          virtType);
}

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
static int
virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr vm,
                                      virStorageSourcePtr src)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

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

    return rc;
}

static int
virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
                                          virDomainDefPtr vm,
                                          virStorageSourcePtr src)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityStackItemPtr item = priv->itemsHead;
    int rc = 0;

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

    return rc;
}

602
virSecurityDriver virSecurityDriverStack = {
603 604 605 606 607
    .privateDataLen                     = sizeof(virSecurityStackData),
    .name                               = "stack",
    .probe                              = virSecurityStackProbe,
    .open                               = virSecurityStackOpen,
    .close                              = virSecurityStackClose,
608

609 610
    .getModel                           = virSecurityStackGetModel,
    .getDOI                             = virSecurityStackGetDOI,
611

612 613
    .preFork                            = virSecurityStackPreFork,

614
    .domainSecurityVerify               = virSecurityStackVerify,
615

616
    .domainSetSecurityDiskLabel         = virSecurityStackSetSecurityDiskLabel,
617
    .domainRestoreSecurityDiskLabel     = virSecurityStackRestoreSecurityDiskLabel,
618

619 620 621
    .domainSetSecurityImageLabel        = virSecurityStackSetSecurityImageLabel,
    .domainRestoreSecurityImageLabel    = virSecurityStackRestoreSecurityImageLabel,

622 623 624
    .domainSetSecurityDaemonSocketLabel = virSecurityStackSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityStackSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityStackClearSocketLabel,
625

626 627 628
    .domainGenSecurityLabel             = virSecurityStackGenLabel,
    .domainReserveSecurityLabel         = virSecurityStackReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityStackReleaseLabel,
629

630 631
    .domainGetSecurityProcessLabel      = virSecurityStackGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityStackSetProcessLabel,
632
    .domainSetSecurityChildProcessLabel = virSecurityStackSetChildProcessLabel,
633

634 635
    .domainSetSecurityAllLabel          = virSecurityStackSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityStackRestoreSecurityAllLabel,
636

637 638
    .domainSetSecurityHostdevLabel      = virSecurityStackSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityStackRestoreSecurityHostdevLabel,
639

640 641
    .domainSetSavedStateLabel           = virSecurityStackSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityStackRestoreSavedStateLabel,
642

643
    .domainSetSecurityImageFDLabel      = virSecurityStackSetImageFDLabel,
644
    .domainSetSecurityTapFDLabel        = virSecurityStackSetTapFDLabel,
645

646
    .domainGetSecurityMountOptions      = virSecurityStackGetMountOptions,
647 648

    .domainSetSecurityHugepages         = virSecurityStackSetHugepages,
649 650

    .getBaseLabel                       = virSecurityStackGetBaseLabel,
651
};