linux/security/smack/smackfs.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
   3 *
   4 *      This program is free software; you can redistribute it and/or modify
   5 *      it under the terms of the GNU General Public License as published by
   6 *      the Free Software Foundation, version 2.
   7 *
   8 * Authors:
   9 *      Casey Schaufler <casey@schaufler-ca.com>
  10 *      Ahmed S. Darwish <darwish.07@gmail.com>
  11 *
  12 * Special thanks to the authors of selinuxfs.
  13 *
  14 *      Karl MacMillan <kmacmillan@tresys.com>
  15 *      James Morris <jmorris@redhat.com>
  16 *
  17 */
  18
  19#include <linux/kernel.h>
  20#include <linux/vmalloc.h>
  21#include <linux/security.h>
  22#include <linux/mutex.h>
  23#include <net/netlabel.h>
  24#include <net/cipso_ipv4.h>
  25#include <linux/seq_file.h>
  26#include <linux/ctype.h>
  27#include <linux/audit.h>
  28#include "smack.h"
  29
  30/*
  31 * smackfs pseudo filesystem.
  32 */
  33
  34enum smk_inos {
  35        SMK_ROOT_INO    = 2,
  36        SMK_LOAD        = 3,    /* load policy */
  37        SMK_CIPSO       = 4,    /* load label -> CIPSO mapping */
  38        SMK_DOI         = 5,    /* CIPSO DOI */
  39        SMK_DIRECT      = 6,    /* CIPSO level indicating direct label */
  40        SMK_AMBIENT     = 7,    /* internet ambient label */
  41        SMK_NLTYPE      = 8,    /* label scheme to use by default */
  42};
  43
  44/*
  45 * List locks
  46 */
  47static DEFINE_MUTEX(smack_list_lock);
  48static DEFINE_MUTEX(smack_cipso_lock);
  49static DEFINE_MUTEX(smack_ambient_lock);
  50
  51/*
  52 * This is the "ambient" label for network traffic.
  53 * If it isn't somehow marked, use this.
  54 * It can be reset via smackfs/ambient
  55 */
  56char *smack_net_ambient = smack_known_floor.smk_known;
  57
  58/*
  59 * This is the default packet marking scheme for network traffic.
  60 * It can be reset via smackfs/nltype
  61 */
  62int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
  63
  64/*
  65 * This is the level in a CIPSO header that indicates a
  66 * smack label is contained directly in the category set.
  67 * It can be reset via smackfs/direct
  68 */
  69int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
  70
  71static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
  72struct smk_list_entry *smack_list;
  73
  74#define SEQ_READ_FINISHED       1
  75
  76/*
  77 * Values for parsing cipso rules
  78 * SMK_DIGITLEN: Length of a digit field in a rule.
  79 * SMK_CIPSOMIN: Minimum possible cipso rule length.
  80 * SMK_CIPSOMAX: Maximum possible cipso rule length.
  81 */
  82#define SMK_DIGITLEN 4
  83#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
  84#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
  85
  86/*
  87 * Values for parsing MAC rules
  88 * SMK_ACCESS: Maximum possible combination of access permissions
  89 * SMK_ACCESSLEN: Maximum length for a rule access field
  90 * SMK_LOADLEN: Smack rule length
  91 */
  92#define SMK_ACCESS    "rwxa"
  93#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
  94#define SMK_LOADLEN   (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
  95
  96
  97/*
  98 * Seq_file read operations for /smack/load
  99 */
 100
 101static void *load_seq_start(struct seq_file *s, loff_t *pos)
 102{
 103        if (*pos == SEQ_READ_FINISHED)
 104                return NULL;
 105
 106        return smack_list;
 107}
 108
 109static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
 110{
 111        struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next;
 112
 113        if (skp == NULL)
 114                *pos = SEQ_READ_FINISHED;
 115
 116        return skp;
 117}
 118
 119static int load_seq_show(struct seq_file *s, void *v)
 120{
 121        struct smk_list_entry *slp = (struct smk_list_entry *) v;
 122        struct smack_rule *srp = &slp->smk_rule;
 123
 124        seq_printf(s, "%s %s", (char *)srp->smk_subject,
 125                   (char *)srp->smk_object);
 126
 127        seq_putc(s, ' ');
 128
 129        if (srp->smk_access & MAY_READ)
 130                seq_putc(s, 'r');
 131        if (srp->smk_access & MAY_WRITE)
 132                seq_putc(s, 'w');
 133        if (srp->smk_access & MAY_EXEC)
 134                seq_putc(s, 'x');
 135        if (srp->smk_access & MAY_APPEND)
 136                seq_putc(s, 'a');
 137        if (srp->smk_access == 0)
 138                seq_putc(s, '-');
 139
 140        seq_putc(s, '\n');
 141
 142        return 0;
 143}
 144
 145static void load_seq_stop(struct seq_file *s, void *v)
 146{
 147        /* No-op */
 148}
 149
 150static struct seq_operations load_seq_ops = {
 151        .start = load_seq_start,
 152        .next  = load_seq_next,
 153        .show  = load_seq_show,
 154        .stop  = load_seq_stop,
 155};
 156
 157/**
 158 * smk_open_load - open() for /smack/load
 159 * @inode: inode structure representing file
 160 * @file: "load" file pointer
 161 *
 162 * For reading, use load_seq_* seq_file reading operations.
 163 */
 164static int smk_open_load(struct inode *inode, struct file *file)
 165{
 166        return seq_open(file, &load_seq_ops);
 167}
 168
 169/**
 170 * smk_set_access - add a rule to the rule list
 171 * @srp: the new rule to add
 172 *
 173 * Looks through the current subject/object/access list for
 174 * the subject/object pair and replaces the access that was
 175 * there. If the pair isn't found add it with the specified
 176 * access.
 177 */
 178static void smk_set_access(struct smack_rule *srp)
 179{
 180        struct smk_list_entry *sp;
 181        struct smk_list_entry *newp;
 182
 183        mutex_lock(&smack_list_lock);
 184
 185        for (sp = smack_list; sp != NULL; sp = sp->smk_next)
 186                if (sp->smk_rule.smk_subject == srp->smk_subject &&
 187                    sp->smk_rule.smk_object == srp->smk_object) {
 188                        sp->smk_rule.smk_access = srp->smk_access;
 189                        break;
 190                }
 191
 192        if (sp == NULL) {
 193                newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
 194                newp->smk_rule = *srp;
 195                newp->smk_next = smack_list;
 196                smack_list = newp;
 197        }
 198
 199        mutex_unlock(&smack_list_lock);
 200
 201        return;
 202}
 203
 204/**
 205 * smk_write_load - write() for /smack/load
 206 * @filp: file pointer, not actually used
 207 * @buf: where to get the data from
 208 * @count: bytes sent
 209 * @ppos: where to start - must be 0
 210 *
 211 * Get one smack access rule from above.
 212 * The format is exactly:
 213 *     char subject[SMK_LABELLEN]
 214 *     char object[SMK_LABELLEN]
 215 *     char access[SMK_ACCESSLEN]
 216 *
 217 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
 218 */
 219static ssize_t smk_write_load(struct file *file, const char __user *buf,
 220                              size_t count, loff_t *ppos)
 221{
 222        struct smack_rule rule;
 223        char *data;
 224        int rc = -EINVAL;
 225
 226        /*
 227         * Must have privilege.
 228         * No partial writes.
 229         * Enough data must be present.
 230         */
 231        if (!capable(CAP_MAC_ADMIN))
 232                return -EPERM;
 233        if (*ppos != 0)
 234                return -EINVAL;
 235        if (count != SMK_LOADLEN)
 236                return -EINVAL;
 237
 238        data = kzalloc(count, GFP_KERNEL);
 239        if (data == NULL)
 240                return -ENOMEM;
 241
 242        if (copy_from_user(data, buf, count) != 0) {
 243                rc = -EFAULT;
 244                goto out;
 245        }
 246
 247        rule.smk_subject = smk_import(data, 0);
 248        if (rule.smk_subject == NULL)
 249                goto out;
 250
 251        rule.smk_object = smk_import(data + SMK_LABELLEN, 0);
 252        if (rule.smk_object == NULL)
 253                goto out;
 254
 255        rule.smk_access = 0;
 256
 257        switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
 258        case '-':
 259                break;
 260        case 'r':
 261        case 'R':
 262                rule.smk_access |= MAY_READ;
 263                break;
 264        default:
 265                goto out;
 266        }
 267
 268        switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
 269        case '-':
 270                break;
 271        case 'w':
 272        case 'W':
 273                rule.smk_access |= MAY_WRITE;
 274                break;
 275        default:
 276                goto out;
 277        }
 278
 279        switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
 280        case '-':
 281                break;
 282        case 'x':
 283        case 'X':
 284                rule.smk_access |= MAY_EXEC;
 285                break;
 286        default:
 287                goto out;
 288        }
 289
 290        switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
 291        case '-':
 292                break;
 293        case 'a':
 294        case 'A':
 295                rule.smk_access |= MAY_READ;
 296                break;
 297        default:
 298                goto out;
 299        }
 300
 301        smk_set_access(&rule);
 302        rc = count;
 303
 304out:
 305        kfree(data);
 306        return rc;
 307}
 308
 309static const struct file_operations smk_load_ops = {
 310        .open           = smk_open_load,
 311        .read           = seq_read,
 312        .llseek         = seq_lseek,
 313        .write          = smk_write_load,
 314        .release        = seq_release,
 315};
 316
 317/**
 318 * smk_cipso_doi - initialize the CIPSO domain
 319 */
 320static void smk_cipso_doi(void)
 321{
 322        int rc;
 323        struct cipso_v4_doi *doip;
 324        struct netlbl_audit audit_info;
 325
 326        audit_info.loginuid = audit_get_loginuid(current);
 327        audit_info.sessionid = audit_get_sessionid(current);
 328        audit_info.secid = smack_to_secid(current->security);
 329
 330        rc = netlbl_cfg_map_del(NULL, &audit_info);
 331        if (rc != 0)
 332                printk(KERN_WARNING "%s:%d remove rc = %d\n",
 333                       __func__, __LINE__, rc);
 334
 335        doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
 336        if (doip == NULL)
 337                panic("smack:  Failed to initialize cipso DOI.\n");
 338        doip->map.std = NULL;
 339        doip->doi = smk_cipso_doi_value;
 340        doip->type = CIPSO_V4_MAP_PASS;
 341        doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
 342        for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
 343                doip->tags[rc] = CIPSO_V4_TAG_INVALID;
 344
 345        rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
 346        if (rc != 0)
 347                printk(KERN_WARNING "%s:%d add rc = %d\n",
 348                       __func__, __LINE__, rc);
 349}
 350
 351/**
 352 * smk_unlbl_ambient - initialize the unlabeled domain
 353 */
 354static void smk_unlbl_ambient(char *oldambient)
 355{
 356        int rc;
 357        struct netlbl_audit audit_info;
 358
 359        audit_info.loginuid = audit_get_loginuid(current);
 360        audit_info.sessionid = audit_get_sessionid(current);
 361        audit_info.secid = smack_to_secid(current->security);
 362
 363        if (oldambient != NULL) {
 364                rc = netlbl_cfg_map_del(oldambient, &audit_info);
 365                if (rc != 0)
 366                        printk(KERN_WARNING "%s:%d remove rc = %d\n",
 367                               __func__, __LINE__, rc);
 368        }
 369
 370        rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info);
 371        if (rc != 0)
 372                printk(KERN_WARNING "%s:%d add rc = %d\n",
 373                       __func__, __LINE__, rc);
 374}
 375
 376/*
 377 * Seq_file read operations for /smack/cipso
 378 */
 379
 380static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
 381{
 382        if (*pos == SEQ_READ_FINISHED)
 383                return NULL;
 384
 385        return smack_known;
 386}
 387
 388static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 389{
 390        struct smack_known *skp = ((struct smack_known *) v)->smk_next;
 391
 392        /*
 393         * Omit labels with no associated cipso value
 394         */
 395        while (skp != NULL && !skp->smk_cipso)
 396                skp = skp->smk_next;
 397
 398        if (skp == NULL)
 399                *pos = SEQ_READ_FINISHED;
 400
 401        return skp;
 402}
 403
 404/*
 405 * Print cipso labels in format:
 406 * label level[/cat[,cat]]
 407 */
 408static int cipso_seq_show(struct seq_file *s, void *v)
 409{
 410        struct smack_known *skp = (struct smack_known *) v;
 411        struct smack_cipso *scp = skp->smk_cipso;
 412        char *cbp;
 413        char sep = '/';
 414        int cat = 1;
 415        int i;
 416        unsigned char m;
 417
 418        if (scp == NULL)
 419                return 0;
 420
 421        seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level);
 422
 423        cbp = scp->smk_catset;
 424        for (i = 0; i < SMK_LABELLEN; i++)
 425                for (m = 0x80; m != 0; m >>= 1) {
 426                        if (m & cbp[i]) {
 427                                seq_printf(s, "%c%d", sep, cat);
 428                                sep = ',';
 429                        }
 430                        cat++;
 431                }
 432
 433        seq_putc(s, '\n');
 434
 435        return 0;
 436}
 437
 438static void cipso_seq_stop(struct seq_file *s, void *v)
 439{
 440        /* No-op */
 441}
 442
 443static struct seq_operations cipso_seq_ops = {
 444        .start = cipso_seq_start,
 445        .stop  = cipso_seq_stop,
 446        .next  = cipso_seq_next,
 447        .show  = cipso_seq_show,
 448};
 449
 450/**
 451 * smk_open_cipso - open() for /smack/cipso
 452 * @inode: inode structure representing file
 453 * @file: "cipso" file pointer
 454 *
 455 * Connect our cipso_seq_* operations with /smack/cipso
 456 * file_operations
 457 */
 458static int smk_open_cipso(struct inode *inode, struct file *file)
 459{
 460        return seq_open(file, &cipso_seq_ops);
 461}
 462
 463/**
 464 * smk_write_cipso - write() for /smack/cipso
 465 * @filp: file pointer, not actually used
 466 * @buf: where to get the data from
 467 * @count: bytes sent
 468 * @ppos: where to start
 469 *
 470 * Accepts only one cipso rule per write call.
 471 * Returns number of bytes written or error code, as appropriate
 472 */
 473static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
 474                               size_t count, loff_t *ppos)
 475{
 476        struct smack_known *skp;
 477        struct smack_cipso *scp = NULL;
 478        char mapcatset[SMK_LABELLEN];
 479        int maplevel;
 480        int cat;
 481        int catlen;
 482        ssize_t rc = -EINVAL;
 483        char *data = NULL;
 484        char *rule;
 485        int ret;
 486        int i;
 487
 488        /*
 489         * Must have privilege.
 490         * No partial writes.
 491         * Enough data must be present.
 492         */
 493        if (!capable(CAP_MAC_ADMIN))
 494                return -EPERM;
 495        if (*ppos != 0)
 496                return -EINVAL;
 497        if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
 498                return -EINVAL;
 499
 500        data = kzalloc(count + 1, GFP_KERNEL);
 501        if (data == NULL)
 502                return -ENOMEM;
 503
 504        if (copy_from_user(data, buf, count) != 0) {
 505                rc = -EFAULT;
 506                goto unlockedout;
 507        }
 508
 509        data[count] = '\0';
 510        rule = data;
 511        /*
 512         * Only allow one writer at a time. Writes should be
 513         * quite rare and small in any case.
 514         */
 515        mutex_lock(&smack_cipso_lock);
 516
 517        skp = smk_import_entry(rule, 0);
 518        if (skp == NULL)
 519                goto out;
 520
 521        rule += SMK_LABELLEN;;
 522        ret = sscanf(rule, "%d", &maplevel);
 523        if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
 524                goto out;
 525
 526        rule += SMK_DIGITLEN;
 527        ret = sscanf(rule, "%d", &catlen);
 528        if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
 529                goto out;
 530
 531        if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
 532                goto out;
 533
 534        memset(mapcatset, 0, sizeof(mapcatset));
 535
 536        for (i = 0; i < catlen; i++) {
 537                rule += SMK_DIGITLEN;
 538                ret = sscanf(rule, "%d", &cat);
 539                if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
 540                        goto out;
 541
 542                smack_catset_bit(cat, mapcatset);
 543        }
 544
 545        if (skp->smk_cipso == NULL) {
 546                scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL);
 547                if (scp == NULL) {
 548                        rc = -ENOMEM;
 549                        goto out;
 550                }
 551        }
 552
 553        spin_lock_bh(&skp->smk_cipsolock);
 554
 555        if (scp == NULL)
 556                scp = skp->smk_cipso;
 557        else
 558                skp->smk_cipso = scp;
 559
 560        scp->smk_level = maplevel;
 561        memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
 562
 563        spin_unlock_bh(&skp->smk_cipsolock);
 564
 565        rc = count;
 566out:
 567        mutex_unlock(&smack_cipso_lock);
 568unlockedout:
 569        kfree(data);
 570        return rc;
 571}
 572
 573static const struct file_operations smk_cipso_ops = {
 574        .open           = smk_open_cipso,
 575        .read           = seq_read,
 576        .llseek         = seq_lseek,
 577        .write          = smk_write_cipso,
 578        .release        = seq_release,
 579};
 580
 581/**
 582 * smk_read_doi - read() for /smack/doi
 583 * @filp: file pointer, not actually used
 584 * @buf: where to put the result
 585 * @count: maximum to send along
 586 * @ppos: where to start
 587 *
 588 * Returns number of bytes read or error code, as appropriate
 589 */
 590static ssize_t smk_read_doi(struct file *filp, char __user *buf,
 591                            size_t count, loff_t *ppos)
 592{
 593        char temp[80];
 594        ssize_t rc;
 595
 596        if (*ppos != 0)
 597                return 0;
 598
 599        sprintf(temp, "%d", smk_cipso_doi_value);
 600        rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
 601
 602        return rc;
 603}
 604
 605/**
 606 * smk_write_doi - write() for /smack/doi
 607 * @filp: file pointer, not actually used
 608 * @buf: where to get the data from
 609 * @count: bytes sent
 610 * @ppos: where to start
 611 *
 612 * Returns number of bytes written or error code, as appropriate
 613 */
 614static ssize_t smk_write_doi(struct file *file, const char __user *buf,
 615                             size_t count, loff_t *ppos)
 616{
 617        char temp[80];
 618        int i;
 619
 620        if (!capable(CAP_MAC_ADMIN))
 621                return -EPERM;
 622
 623        if (count >= sizeof(temp) || count == 0)
 624                return -EINVAL;
 625
 626        if (copy_from_user(temp, buf, count) != 0)
 627                return -EFAULT;
 628
 629        temp[count] = '\0';
 630
 631        if (sscanf(temp, "%d", &i) != 1)
 632                return -EINVAL;
 633
 634        smk_cipso_doi_value = i;
 635
 636        smk_cipso_doi();
 637
 638        return count;
 639}
 640
 641static const struct file_operations smk_doi_ops = {
 642        .read           = smk_read_doi,
 643        .write          = smk_write_doi,
 644};
 645
 646/**
 647 * smk_read_direct - read() for /smack/direct
 648 * @filp: file pointer, not actually used
 649 * @buf: where to put the result
 650 * @count: maximum to send along
 651 * @ppos: where to start
 652 *
 653 * Returns number of bytes read or error code, as appropriate
 654 */
 655static ssize_t smk_read_direct(struct file *filp, char __user *buf,
 656                               size_t count, loff_t *ppos)
 657{
 658        char temp[80];
 659        ssize_t rc;
 660
 661        if (*ppos != 0)
 662                return 0;
 663
 664        sprintf(temp, "%d", smack_cipso_direct);
 665        rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
 666
 667        return rc;
 668}
 669
 670/**
 671 * smk_write_direct - write() for /smack/direct
 672 * @filp: file pointer, not actually used
 673 * @buf: where to get the data from
 674 * @count: bytes sent
 675 * @ppos: where to start
 676 *
 677 * Returns number of bytes written or error code, as appropriate
 678 */
 679static ssize_t smk_write_direct(struct file *file, const char __user *buf,
 680                                size_t count, loff_t *ppos)
 681{
 682        char temp[80];
 683        int i;
 684
 685        if (!capable(CAP_MAC_ADMIN))
 686                return -EPERM;
 687
 688        if (count >= sizeof(temp) || count == 0)
 689                return -EINVAL;
 690
 691        if (copy_from_user(temp, buf, count) != 0)
 692                return -EFAULT;
 693
 694        temp[count] = '\0';
 695
 696        if (sscanf(temp, "%d", &i) != 1)
 697                return -EINVAL;
 698
 699        smack_cipso_direct = i;
 700
 701        return count;
 702}
 703
 704static const struct file_operations smk_direct_ops = {
 705        .read           = smk_read_direct,
 706        .write          = smk_write_direct,
 707};
 708
 709/**
 710 * smk_read_ambient - read() for /smack/ambient
 711 * @filp: file pointer, not actually used
 712 * @buf: where to put the result
 713 * @cn: maximum to send along
 714 * @ppos: where to start
 715 *
 716 * Returns number of bytes read or error code, as appropriate
 717 */
 718static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
 719                                size_t cn, loff_t *ppos)
 720{
 721        ssize_t rc;
 722        int asize;
 723
 724        if (*ppos != 0)
 725                return 0;
 726        /*
 727         * Being careful to avoid a problem in the case where
 728         * smack_net_ambient gets changed in midstream.
 729         */
 730        mutex_lock(&smack_ambient_lock);
 731
 732        asize = strlen(smack_net_ambient) + 1;
 733
 734        if (cn >= asize)
 735                rc = simple_read_from_buffer(buf, cn, ppos,
 736                                             smack_net_ambient, asize);
 737        else
 738                rc = -EINVAL;
 739
 740        mutex_unlock(&smack_ambient_lock);
 741
 742        return rc;
 743}
 744
 745/**
 746 * smk_write_ambient - write() for /smack/ambient
 747 * @filp: file pointer, not actually used
 748 * @buf: where to get the data from
 749 * @count: bytes sent
 750 * @ppos: where to start
 751 *
 752 * Returns number of bytes written or error code, as appropriate
 753 */
 754static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
 755                                 size_t count, loff_t *ppos)
 756{
 757        char in[SMK_LABELLEN];
 758        char *oldambient;
 759        char *smack;
 760
 761        if (!capable(CAP_MAC_ADMIN))
 762                return -EPERM;
 763
 764        if (count >= SMK_LABELLEN)
 765                return -EINVAL;
 766
 767        if (copy_from_user(in, buf, count) != 0)
 768                return -EFAULT;
 769
 770        smack = smk_import(in, count);
 771        if (smack == NULL)
 772                return -EINVAL;
 773
 774        mutex_lock(&smack_ambient_lock);
 775
 776        oldambient = smack_net_ambient;
 777        smack_net_ambient = smack;
 778        smk_unlbl_ambient(oldambient);
 779
 780        mutex_unlock(&smack_ambient_lock);
 781
 782        return count;
 783}
 784
 785static const struct file_operations smk_ambient_ops = {
 786        .read           = smk_read_ambient,
 787        .write          = smk_write_ambient,
 788};
 789
 790struct option_names {
 791        int     o_number;
 792        char    *o_name;
 793        char    *o_alias;
 794};
 795
 796static struct option_names netlbl_choices[] = {
 797        { NETLBL_NLTYPE_RIPSO,
 798                NETLBL_NLTYPE_RIPSO_NAME,       "ripso" },
 799        { NETLBL_NLTYPE_CIPSOV4,
 800                NETLBL_NLTYPE_CIPSOV4_NAME,     "cipsov4" },
 801        { NETLBL_NLTYPE_CIPSOV4,
 802                NETLBL_NLTYPE_CIPSOV4_NAME,     "cipso" },
 803        { NETLBL_NLTYPE_CIPSOV6,
 804                NETLBL_NLTYPE_CIPSOV6_NAME,     "cipsov6" },
 805        { NETLBL_NLTYPE_UNLABELED,
 806                NETLBL_NLTYPE_UNLABELED_NAME,   "unlabeled" },
 807};
 808
 809/**
 810 * smk_read_nltype - read() for /smack/nltype
 811 * @filp: file pointer, not actually used
 812 * @buf: where to put the result
 813 * @count: maximum to send along
 814 * @ppos: where to start
 815 *
 816 * Returns number of bytes read or error code, as appropriate
 817 */
 818static ssize_t smk_read_nltype(struct file *filp, char __user *buf,
 819                               size_t count, loff_t *ppos)
 820{
 821        char bound[40];
 822        ssize_t rc;
 823        int i;
 824
 825        if (count < SMK_LABELLEN)
 826                return -EINVAL;
 827
 828        if (*ppos != 0)
 829                return 0;
 830
 831        sprintf(bound, "unknown");
 832
 833        for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
 834                if (smack_net_nltype == netlbl_choices[i].o_number) {
 835                        sprintf(bound, "%s", netlbl_choices[i].o_name);
 836                        break;
 837                }
 838
 839        rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));
 840
 841        return rc;
 842}
 843
 844/**
 845 * smk_write_nltype - write() for /smack/nltype
 846 * @filp: file pointer, not actually used
 847 * @buf: where to get the data from
 848 * @count: bytes sent
 849 * @ppos: where to start
 850 *
 851 * Returns number of bytes written or error code, as appropriate
 852 */
 853static ssize_t smk_write_nltype(struct file *file, const char __user *buf,
 854                                size_t count, loff_t *ppos)
 855{
 856        char bound[40];
 857        char *cp;
 858        int i;
 859
 860        if (!capable(CAP_MAC_ADMIN))
 861                return -EPERM;
 862
 863        if (count >= 40)
 864                return -EINVAL;
 865
 866        if (copy_from_user(bound, buf, count) != 0)
 867                return -EFAULT;
 868
 869        bound[count] = '\0';
 870        cp = strchr(bound, ' ');
 871        if (cp != NULL)
 872                *cp = '\0';
 873        cp = strchr(bound, '\n');
 874        if (cp != NULL)
 875                *cp = '\0';
 876
 877        for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
 878                if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||
 879                    strcmp(bound, netlbl_choices[i].o_alias) == 0) {
 880                        smack_net_nltype = netlbl_choices[i].o_number;
 881                        return count;
 882                }
 883        /*
 884         * Not a valid choice.
 885         */
 886        return -EINVAL;
 887}
 888
 889static const struct file_operations smk_nltype_ops = {
 890        .read           = smk_read_nltype,
 891        .write          = smk_write_nltype,
 892};
 893
 894/**
 895 * smk_fill_super - fill the /smackfs superblock
 896 * @sb: the empty superblock
 897 * @data: unused
 898 * @silent: unused
 899 *
 900 * Fill in the well known entries for /smack
 901 *
 902 * Returns 0 on success, an error code on failure
 903 */
 904static int smk_fill_super(struct super_block *sb, void *data, int silent)
 905{
 906        int rc;
 907        struct inode *root_inode;
 908
 909        static struct tree_descr smack_files[] = {
 910                [SMK_LOAD]      =
 911                        {"load", &smk_load_ops, S_IRUGO|S_IWUSR},
 912                [SMK_CIPSO]     =
 913                        {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
 914                [SMK_DOI]       =
 915                        {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
 916                [SMK_DIRECT]    =
 917                        {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
 918                [SMK_AMBIENT]   =
 919                        {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
 920                [SMK_NLTYPE]    =
 921                        {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
 922                /* last one */ {""}
 923        };
 924
 925        rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
 926        if (rc != 0) {
 927                printk(KERN_ERR "%s failed %d while creating inodes\n",
 928                        __func__, rc);
 929                return rc;
 930        }
 931
 932        root_inode = sb->s_root->d_inode;
 933        root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
 934
 935        return 0;
 936}
 937
 938/**
 939 * smk_get_sb - get the smackfs superblock
 940 * @fs_type: passed along without comment
 941 * @flags: passed along without comment
 942 * @dev_name: passed along without comment
 943 * @data: passed along without comment
 944 * @mnt: passed along without comment
 945 *
 946 * Just passes everything along.
 947 *
 948 * Returns what the lower level code does.
 949 */
 950static int smk_get_sb(struct file_system_type *fs_type,
 951                      int flags, const char *dev_name, void *data,
 952                      struct vfsmount *mnt)
 953{
 954        return get_sb_single(fs_type, flags, data, smk_fill_super, mnt);
 955}
 956
 957static struct file_system_type smk_fs_type = {
 958        .name           = "smackfs",
 959        .get_sb         = smk_get_sb,
 960        .kill_sb        = kill_litter_super,
 961};
 962
 963static struct vfsmount *smackfs_mount;
 964
 965/**
 966 * init_smk_fs - get the smackfs superblock
 967 *
 968 * register the smackfs
 969 *
 970 * Do not register smackfs if Smack wasn't enabled
 971 * on boot. We can not put this method normally under the
 972 * smack_init() code path since the security subsystem get
 973 * initialized before the vfs caches.
 974 *
 975 * Returns true if we were not chosen on boot or if
 976 * we were chosen and filesystem registration succeeded.
 977 */
 978static int __init init_smk_fs(void)
 979{
 980        int err;
 981
 982        if (!security_module_enable(&smack_ops))
 983                return 0;
 984
 985        err = register_filesystem(&smk_fs_type);
 986        if (!err) {
 987                smackfs_mount = kern_mount(&smk_fs_type);
 988                if (IS_ERR(smackfs_mount)) {
 989                        printk(KERN_ERR "smackfs:  could not mount!\n");
 990                        err = PTR_ERR(smackfs_mount);
 991                        smackfs_mount = NULL;
 992                }
 993        }
 994
 995        smk_cipso_doi();
 996        smk_unlbl_ambient(NULL);
 997
 998        return err;
 999}
1000
1001__initcall(init_smk_fs);
1002