2 * chsmack - Set smack attributes on files
4 * Copyright (C) 2011 Nokia Corporation.
5 * Copyright (C) 2011, 2012, 2013 Intel Corporation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 #include <sys/types.h>
24 #include <sys/xattr.h>
25 #include <linux/xattr.h>
26 #include <sys/smack.h>
36 static const char usage[] =
37 "Usage: %s [options] <path>\n"
39 " -v --version output version information and exit\n"
40 " -h --help output usage information and exit\n"
41 " -a --access set/remove "XATTR_NAME_SMACK"\n"
42 " -e --exec set/remove "XATTR_NAME_SMACKEXEC"\n"
43 " -m --mmap set/remove "XATTR_NAME_SMACKMMAP"\n"
44 " -t --transmute set/remove "XATTR_NAME_SMACKTRANSMUTE"\n"
45 " -d --remove tell to remove the attribute\n"
46 " -L --dereference tell to follow the symbolic links\n"
50 int main(int argc, char *argv[])
52 static const char shortoptions[] = "vha::e::m::tdL";
53 static struct option options[] = {
54 {"version", no_argument, 0, 'v'},
55 {"help", no_argument, 0, 'h'},
56 {"access", optional_argument, 0, 'a'},
57 {"exec", optional_argument, 0, 'e'},
58 {"mmap", optional_argument, 0, 'm'},
59 {"transmute", no_argument, 0, 't'},
60 {"dereference", no_argument, 0, 'L'},
64 /* Buffers are zeroed automatically by keeping them static variables.
65 * No separate memset is needed this way.
67 static int options_map[128];
69 /* structure for recording options of label and their init */
71 int isset; /* 0 if option not set, 1 if option set */
72 const char *value; /* value of the option set if any or NULL else */
74 struct labelset access_set = { 0, NULL }; /* for option "access" */
75 struct labelset exec_set = { 0, NULL }; /* for option "exec" */
76 struct labelset mmap_set = { 0, NULL }; /* for option "mmap" */
78 struct labelset *labelset;
84 int transmute_flag = 0;
90 for (i = 0; options[i].name != NULL; i++)
91 options_map[options[i].val] = i;
93 /* scan options without argument */
94 while ((c = getopt_long(argc, argv, shortoptions, options, NULL)) != -1) {
100 /* greedy on optional arguments */
101 if (optarg == NULL && argv[optind] != NULL
102 && argv[optind][0] != '-') {
108 fprintf(stderr, "%s: %s: option set many times.\n",
109 basename(argv[0]), options[options_map[c]].name);
115 fprintf(stderr, "%s: %s: option set many times.\n",
116 basename(argv[0]), options[options_map[c]].name);
121 fprintf(stderr, "%s: %s: option set many times.\n",
122 basename(argv[0]), options[options_map[c]].name);
126 printf("%s (libsmack) version " PACKAGE_VERSION "\n",
130 printf(usage, basename(argv[0]));
133 printf(usage, basename(argv[0]));
138 /* scan options with argument (possibly) */
140 while ((c = getopt_long(argc, argv, shortoptions, options, NULL)) != -1) {
144 labelset = &access_set;
147 labelset = &exec_set;
150 labelset = &mmap_set;
156 if (labelset->isset) {
157 fprintf(stderr, "%s: %s: option set many times.\n",
158 basename(argv[0]), options[options_map[c]].name);
161 /* greedy on optional arguments */
162 if (optarg == NULL && argv[optind] != NULL && argv[optind][0] != '-') {
163 optarg = argv[optind++];
165 if (optarg == NULL) {
167 fprintf(stderr, "%s: %s: requires a label when setting.\n",
168 basename(argv[0]), options[options_map[c]].name);
172 else if (delete_flag) {
173 fprintf(stderr, "%s: %s: requires no label when deleting.\n",
174 basename(argv[0]), options[options_map[c]].name);
177 else if (strnlen(optarg, SMACK_LABEL_LEN + 1) == SMACK_LABEL_LEN + 1) {
178 fprintf(stderr, "%s: %s: \"%s\" exceeds %d characters.\n",
179 basename(argv[0]), options[options_map[c]].name, optarg,
183 else if (smack_label_length(optarg) < 0) {
184 fprintf(stderr, "%s: %s: \"%s\" is an invalid Smack label.\n",
185 basename(argv[0]), options[options_map[c]].name, optarg);
189 labelset->value = optarg;
193 /* deleting labels */
196 access_set.isset = 1;
201 for (i = optind; i < argc; i++) {
202 if (access_set.isset) {
203 rc = smack_remove_label_for_path(argv[i],
204 XATTR_NAME_SMACK, follow_flag);
205 if (rc < 0 && (option_flag || errno != ENODATA))
209 if (exec_set.isset) {
210 rc = smack_remove_label_for_path(argv[i],
211 XATTR_NAME_SMACKEXEC, follow_flag);
212 if (rc < 0 && (option_flag || errno != ENODATA))
216 if (mmap_set.isset) {
217 rc = smack_remove_label_for_path(argv[i],
218 XATTR_NAME_SMACKMMAP, follow_flag);
219 if (rc < 0 && (option_flag || errno != ENODATA))
223 if (transmute_flag) {
224 rc = smack_remove_label_for_path(argv[i],
225 XATTR_NAME_SMACKTRANSMUTE, follow_flag);
226 if (rc < 0 && (option_flag || errno != ENODATA))
233 else if (option_flag) {
234 for (i = optind; i < argc; i++) {
235 if (access_set.isset) {
236 rc = smack_set_label_for_path(argv[i],
237 XATTR_NAME_SMACK, follow_flag, access_set.value);
242 if (exec_set.isset) {
243 rc = smack_set_label_for_path(argv[i],
244 XATTR_NAME_SMACKEXEC, follow_flag, exec_set.value);
249 if (mmap_set.isset) {
250 rc = smack_set_label_for_path(argv[i],
251 XATTR_NAME_SMACKMMAP, follow_flag, mmap_set.value);
256 if (transmute_flag) {
257 rc = follow_flag ? stat(argv[i], &st) : lstat(argv[i], &st);
260 else if (!S_ISDIR(st.st_mode)) {
261 fprintf(stderr, "%s: transmute: not a directory %s\n",
262 basename(argv[0]), argv[i]);
265 rc = smack_set_label_for_path(argv[i],
266 XATTR_NAME_SMACKTRANSMUTE, follow_flag, "TRUE");
276 for (i = optind; i < argc; i++) {
278 /* Print file path. */
279 printf("%s", argv[i]);
281 rc = (int)smack_new_label_from_path(argv[i],
282 XATTR_NAME_SMACK, follow_flag, &label);
284 printf(" access=\"%s\"", label);
288 rc = (int)smack_new_label_from_path(argv[i],
289 XATTR_NAME_SMACKEXEC, follow_flag, &label);
291 printf(" execute=\"%s\"", label);
295 rc = (int)smack_new_label_from_path(argv[i],
296 XATTR_NAME_SMACKMMAP, follow_flag, &label);
298 printf(" mmap=\"%s\"", label);
302 rc = (int)smack_new_label_from_path(argv[i],
303 XATTR_NAME_SMACKTRANSMUTE, follow_flag, &label);
305 printf(" transmute=\"%s\"", label);