1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
263e2b423SJohn Johansen /*
363e2b423SJohn Johansen * AppArmor security module
463e2b423SJohn Johansen *
563e2b423SJohn Johansen * This file contains AppArmor /proc/<pid>/attr/ interface functions
663e2b423SJohn Johansen *
763e2b423SJohn Johansen * Copyright (C) 1998-2008 Novell/SUSE
863e2b423SJohn Johansen * Copyright 2009-2010 Canonical Ltd.
963e2b423SJohn Johansen */
1063e2b423SJohn Johansen
1163e2b423SJohn Johansen #include "include/apparmor.h"
12d8889d49SJohn Johansen #include "include/cred.h"
1363e2b423SJohn Johansen #include "include/policy.h"
14cff281f6SJohn Johansen #include "include/policy_ns.h"
1563e2b423SJohn Johansen #include "include/domain.h"
16cc7db099SJames Morris #include "include/procattr.h"
1763e2b423SJohn Johansen
1863e2b423SJohn Johansen
1963e2b423SJohn Johansen /**
20*1f2bc06aSGaosheng Cui * aa_getprocattr - Return the label information for @label
21*1f2bc06aSGaosheng Cui * @label: the label to print label info about (NOT NULL)
22*1f2bc06aSGaosheng Cui * @string: Returns - string containing the label info (NOT NULL)
2363e2b423SJohn Johansen *
24*1f2bc06aSGaosheng Cui * Requires: label != NULL && string != NULL
2563e2b423SJohn Johansen *
26*1f2bc06aSGaosheng Cui * Creates a string containing the label information for @label.
2763e2b423SJohn Johansen *
2863e2b423SJohn Johansen * Returns: size of string placed in @string else error code on failure
2963e2b423SJohn Johansen */
aa_getprocattr(struct aa_label * label,char ** string)3076a1d263SJohn Johansen int aa_getprocattr(struct aa_label *label, char **string)
3163e2b423SJohn Johansen {
3276a1d263SJohn Johansen struct aa_ns *ns = labels_ns(label);
33cf797c0eSJohn Johansen struct aa_ns *current_ns = aa_get_current_ns();
3476a1d263SJohn Johansen int len;
3563e2b423SJohn Johansen
3676a1d263SJohn Johansen if (!aa_ns_visible(current_ns, ns, true)) {
37cf797c0eSJohn Johansen aa_put_ns(current_ns);
3876a1d263SJohn Johansen return -EACCES;
3976a1d263SJohn Johansen }
4063e2b423SJohn Johansen
4176a1d263SJohn Johansen len = aa_label_snxprint(NULL, 0, current_ns, label,
4276a1d263SJohn Johansen FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
4376a1d263SJohn Johansen FLAG_HIDDEN_UNCONFINED);
4476a1d263SJohn Johansen AA_BUG(len < 0);
4576a1d263SJohn Johansen
4676a1d263SJohn Johansen *string = kmalloc(len + 2, GFP_KERNEL);
4776a1d263SJohn Johansen if (!*string) {
4876a1d263SJohn Johansen aa_put_ns(current_ns);
4976a1d263SJohn Johansen return -ENOMEM;
5076a1d263SJohn Johansen }
5176a1d263SJohn Johansen
5276a1d263SJohn Johansen len = aa_label_snxprint(*string, len + 2, current_ns, label,
5376a1d263SJohn Johansen FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
5476a1d263SJohn Johansen FLAG_HIDDEN_UNCONFINED);
5576a1d263SJohn Johansen if (len < 0) {
5676a1d263SJohn Johansen aa_put_ns(current_ns);
5763e2b423SJohn Johansen return len;
5863e2b423SJohn Johansen }
5963e2b423SJohn Johansen
6076a1d263SJohn Johansen (*string)[len] = '\n';
6176a1d263SJohn Johansen (*string)[len + 1] = 0;
6276a1d263SJohn Johansen
6376a1d263SJohn Johansen aa_put_ns(current_ns);
6476a1d263SJohn Johansen return len + 1;
6576a1d263SJohn Johansen }
6676a1d263SJohn Johansen
6763e2b423SJohn Johansen /**
6863e2b423SJohn Johansen * split_token_from_name - separate a string of form <token>^<name>
6963e2b423SJohn Johansen * @op: operation being checked
7063e2b423SJohn Johansen * @args: string to parse (NOT NULL)
7163e2b423SJohn Johansen * @token: stores returned parsed token value (NOT NULL)
7263e2b423SJohn Johansen *
7363e2b423SJohn Johansen * Returns: start position of name after token else NULL on failure
7463e2b423SJohn Johansen */
split_token_from_name(const char * op,char * args,u64 * token)7547f6e5ccSJohn Johansen static char *split_token_from_name(const char *op, char *args, u64 *token)
7663e2b423SJohn Johansen {
7763e2b423SJohn Johansen char *name;
7863e2b423SJohn Johansen
7963e2b423SJohn Johansen *token = simple_strtoull(args, &name, 16);
8063e2b423SJohn Johansen if ((name == args) || *name != '^') {
8147f6e5ccSJohn Johansen AA_ERROR("%s: Invalid input '%s'", op, args);
8263e2b423SJohn Johansen return ERR_PTR(-EINVAL);
8363e2b423SJohn Johansen }
8463e2b423SJohn Johansen
8563e2b423SJohn Johansen name++; /* skip ^ */
8663e2b423SJohn Johansen if (!*name)
8763e2b423SJohn Johansen name = NULL;
8863e2b423SJohn Johansen return name;
8963e2b423SJohn Johansen }
9063e2b423SJohn Johansen
9163e2b423SJohn Johansen /**
92240516dfSYang Li * aa_setprocattr_changehat - handle procattr interface to change_hat
9363e2b423SJohn Johansen * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
9463e2b423SJohn Johansen * @size: size of the args
95df8073c6SJohn Johansen * @flags: set of flags governing behavior
9663e2b423SJohn Johansen *
9763e2b423SJohn Johansen * Returns: %0 or error code if change_hat fails
9863e2b423SJohn Johansen */
aa_setprocattr_changehat(char * args,size_t size,int flags)99df8073c6SJohn Johansen int aa_setprocattr_changehat(char *args, size_t size, int flags)
10063e2b423SJohn Johansen {
10163e2b423SJohn Johansen char *hat;
10263e2b423SJohn Johansen u64 token;
10363e2b423SJohn Johansen const char *hats[16]; /* current hard limit on # of names */
10463e2b423SJohn Johansen int count = 0;
10563e2b423SJohn Johansen
10663e2b423SJohn Johansen hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
10763e2b423SJohn Johansen if (IS_ERR(hat))
10863e2b423SJohn Johansen return PTR_ERR(hat);
10963e2b423SJohn Johansen
11063e2b423SJohn Johansen if (!hat && !token) {
11163e2b423SJohn Johansen AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
11263e2b423SJohn Johansen return -EINVAL;
11363e2b423SJohn Johansen }
11463e2b423SJohn Johansen
11563e2b423SJohn Johansen if (hat) {
11663e2b423SJohn Johansen /* set up hat name vector, args guaranteed null terminated
11763e2b423SJohn Johansen * at args[size] by setprocattr.
11863e2b423SJohn Johansen *
11963e2b423SJohn Johansen * If there are multiple hat names in the buffer each is
12063e2b423SJohn Johansen * separated by a \0. Ie. userspace writes them pre tokenized
12163e2b423SJohn Johansen */
12263e2b423SJohn Johansen char *end = args + size;
12363e2b423SJohn Johansen for (count = 0; (hat < end) && count < 16; ++count) {
12463e2b423SJohn Johansen char *next = hat + strlen(hat) + 1;
12563e2b423SJohn Johansen hats[count] = hat;
126c3e1e584SJohn Johansen AA_DEBUG("%s: (pid %d) Magic 0x%llx count %d hat '%s'\n"
127c3e1e584SJohn Johansen , __func__, current->pid, token, count, hat);
12863e2b423SJohn Johansen hat = next;
12963e2b423SJohn Johansen }
130c3e1e584SJohn Johansen } else
131c3e1e584SJohn Johansen AA_DEBUG("%s: (pid %d) Magic 0x%llx count %d Hat '%s'\n",
132c3e1e584SJohn Johansen __func__, current->pid, token, count, "<NULL>");
13363e2b423SJohn Johansen
134df8073c6SJohn Johansen return aa_change_hat(hats, count, token, flags);
13563e2b423SJohn Johansen }
136