security_stack.c 14.7 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
O
Osier Yang 已提交
15 16
 * License along with this library;  If not, see
 * <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 "memory.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 41

struct _virSecurityStackData {
    virSecurityManagerPtr primary;
42
    virSecurityStackItemPtr itemsHead;
43 44
};

45 46 47
int
virSecurityStackAddPrimary(virSecurityManagerPtr mgr,
                           virSecurityManagerPtr primary)
48 49
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
50 51
    if (virSecurityStackAddNested(mgr, primary) < 0)
        return -1;
52
    priv->primary = primary;
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    return 0;
}

int
virSecurityStackAddNested(virSecurityManagerPtr mgr,
                          virSecurityManagerPtr nested)
{
    virSecurityStackItemPtr item = NULL;
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (VIR_ALLOC(item) < 0) {
        virReportOOMError();
        return -1;
    }
    item->securityManager = nested;
    item->next = priv->itemsHead;
    priv->itemsHead = item;
    return 0;
}

virSecurityManagerPtr
virSecurityStackGetPrimary(virSecurityManagerPtr mgr)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return (priv->primary) ? priv->primary : priv->itemsHead->securityManager;
}

void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
                                virSecurityManagerPtr primary)
{
    virSecurityStackAddPrimary(mgr, primary);
84 85 86 87 88
}

void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
                                  virSecurityManagerPtr secondary)
{
89
    virSecurityStackAddNested(mgr, secondary);
90 91 92
}

static virSecurityDriverStatus
93
virSecurityStackProbe(const char *virtDriver ATTRIBUTE_UNUSED)
94 95 96 97 98 99 100 101 102 103 104
{
    return SECURITY_DRIVER_ENABLE;
}

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

static int
E
Eric Blake 已提交
105
virSecurityStackClose(virSecurityManagerPtr mgr)
106
{
E
Eric Blake 已提交
107
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
108
    virSecurityStackItemPtr next, item = priv->itemsHead;
E
Eric Blake 已提交
109

110 111 112 113 114 115
    while (item) {
        next = item->next;
        virSecurityManagerFree(item->securityManager);
        VIR_FREE(item);
        item = next;
    }
E
Eric Blake 已提交
116

117 118 119 120 121 122
    return 0;
}

static const char *
virSecurityStackGetModel(virSecurityManagerPtr mgr)
{
123
    return virSecurityManagerGetModel(virSecurityStackGetPrimary(mgr));
124 125 126 127 128
}

static const char *
virSecurityStackGetDOI(virSecurityManagerPtr mgr)
{
129
    return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
130 131 132 133 134 135 136
}

static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
137
    virSecurityStackItemPtr item = priv->itemsHead;
138 139
    int rc = 0;

140 141 142 143 144 145
    for(; item; item = item->next) {
        if (virSecurityManagerVerify(item->securityManager, def) < 0) {
            rc = -1;
            break;
        }
    }
146 147 148 149 150 151 152

    return rc;
}


static int
virSecurityStackGenLabel(virSecurityManagerPtr mgr,
153
                         virDomainDefPtr vm)
154 155 156
{
    int rc = 0;

157
    if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
158 159
        rc = -1;

160
// TODO
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
#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,
178
                             virDomainDefPtr vm)
179 180 181
{
    int rc = 0;

182
    if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
183
        rc = -1;
184 185

// TODO
186 187 188 189 190 191 192 193 194 195 196 197
#if 0
    /* XXX See note in GenLabel */
    if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
        rc = -1;
#endif

    return rc;
}


static int
virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
198 199
                             virDomainDefPtr vm,
                             pid_t pid)
200 201 202
{
    int rc = 0;

203
    if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
204
        rc = -1;
205
// TODO
206 207
#if 0
    /* XXX See note in GenLabel */
208
    if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
209 210 211 212 213 214 215 216 217
        rc = -1;
#endif

    return rc;
}


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

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

    return rc;
}


static int
virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
236
                                          virDomainDefPtr vm,
237 238 239
                                          virDomainDiskDefPtr disk)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
240
    virSecurityStackItemPtr item = priv->itemsHead;
241 242
    int rc = 0;

243 244 245 246
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreImageLabel(item->securityManager, vm, disk) < 0)
            rc = -1;
    }
247 248 249 250 251 252 253

    return rc;
}


static int
virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
254
                                        virDomainDefPtr vm,
255 256 257 258
                                        virDomainHostdevDefPtr dev)

{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
259
    virSecurityStackItemPtr item = priv->itemsHead;
260 261
    int rc = 0;

262 263 264 265
    for (; item; item = item->next) {
        if (virSecurityManagerSetHostdevLabel(item->securityManager, vm, dev) < 0)
            rc = -1;
    }
266 267 268 269 270 271 272

    return rc;
}


static int
virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
273
                                            virDomainDefPtr vm,
274 275 276
                                            virDomainHostdevDefPtr dev)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
277
    virSecurityStackItemPtr item = priv->itemsHead;
278 279
    int rc = 0;

280 281 282 283
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreHostdevLabel(item->securityManager, vm, dev) < 0)
            rc = -1;
    }
284 285 286 287 288 289 290

    return rc;
}


static int
virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
291
                                    virDomainDefPtr vm,
292 293 294
                                    const char *stdin_path)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
295
    virSecurityStackItemPtr item = priv->itemsHead;
296 297
    int rc = 0;

298 299 300 301
    for (; item; item = item->next) {
        if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
            rc = -1;
    }
302 303 304 305 306 307 308

    return rc;
}


static int
virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
309
                                        virDomainDefPtr vm,
310 311 312
                                        int migrated)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
313
    virSecurityStackItemPtr item = priv->itemsHead;
314 315
    int rc = 0;

316 317 318 319
    for (; item; item = item->next) {
        if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
            rc = -1;
    }
320 321 322 323 324 325 326

    return rc;
}


static int
virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
327
                                   virDomainDefPtr vm,
328 329 330
                                   const char *savefile)
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
331
    virSecurityStackItemPtr item = priv->itemsHead;
332 333
    int rc = 0;

334 335 336 337
    for (; item; item = item->next) {
        if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
            rc = -1;
    }
338 339 340 341 342 343 344

    return rc;
}


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

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

    return rc;
}


static int
virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
363
                                virDomainDefPtr vm)
364 365
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
366
    virSecurityStackItemPtr item = priv->itemsHead;
367 368
    int rc = 0;

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

    return rc;
}

static int
virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
379 380
                                virDomainDefPtr vm,
                                pid_t pid,
381 382 383 384
                                virSecurityLabelPtr seclabel)
{
    int rc = 0;

385
// TODO
386
#if 0
387
    if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
388 389
        rc = -1;
#endif
390
    if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
391 392 393 394 395 396 397
        rc = -1;

    return rc;
}


static int
398
virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
399
                                     virDomainDefPtr vm)
400 401
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
402
    virSecurityStackItemPtr item = priv->itemsHead;
403 404
    int rc = 0;

405 406 407 408
    for (; item; item = item->next) {
        if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
409 410 411 412 413

    return rc;
}


414 415
static int
virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
416
                               virDomainDefPtr vm)
417 418
{
    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
419
    virSecurityStackItemPtr item = priv->itemsHead;
420 421
    int rc = 0;

422 423 424 425
    for (; item; item = item->next) {
        if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
            rc = -1;
    }
426 427 428 429 430

    return rc;
}


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

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

    return rc;
}

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

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

    return rc;
}

464 465 466 467
static char *virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                             virDomainDefPtr vm ATTRIBUTE_UNUSED) {
    return NULL;
}
468

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
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;
}

492
virSecurityDriver virSecurityDriverStack = {
493 494 495 496 497
    .privateDataLen                     = sizeof(virSecurityStackData),
    .name                               = "stack",
    .probe                              = virSecurityStackProbe,
    .open                               = virSecurityStackOpen,
    .close                              = virSecurityStackClose,
498

499 500
    .getModel                           = virSecurityStackGetModel,
    .getDOI                             = virSecurityStackGetDOI,
501

502
    .domainSecurityVerify               = virSecurityStackVerify,
503

504 505
    .domainSetSecurityImageLabel        = virSecurityStackSetSecurityImageLabel,
    .domainRestoreSecurityImageLabel    = virSecurityStackRestoreSecurityImageLabel,
506

507 508 509
    .domainSetSecurityDaemonSocketLabel = virSecurityStackSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityStackSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityStackClearSocketLabel,
510

511 512 513
    .domainGenSecurityLabel             = virSecurityStackGenLabel,
    .domainReserveSecurityLabel         = virSecurityStackReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityStackReleaseLabel,
514

515 516
    .domainGetSecurityProcessLabel      = virSecurityStackGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityStackSetProcessLabel,
517

518 519
    .domainSetSecurityAllLabel          = virSecurityStackSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityStackRestoreSecurityAllLabel,
520

521 522
    .domainSetSecurityHostdevLabel      = virSecurityStackSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityStackRestoreSecurityHostdevLabel,
523

524 525
    .domainSetSavedStateLabel           = virSecurityStackSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityStackRestoreSavedStateLabel,
526

527
    .domainSetSecurityImageFDLabel      = virSecurityStackSetImageFDLabel,
528

529
    .domainGetSecurityMountOptions      = virSecurityStackGetMountOptions,
530
};