summaryrefslogtreecommitdiff
path: root/src/rstsmack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rstsmack.c')
-rw-r--r--src/rstsmack.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/rstsmack.c b/src/rstsmack.c
new file mode 100644
index 0000000..38d18d5
--- /dev/null
+++ b/src/rstsmack.c
@@ -0,0 +1,148 @@
+/*
+ * rstsmack - Restore smack attributes on files
+ *
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd.
+ *
+ * Contact: MyoungJune Park <mj2004.park@samsung.com>
+ * Created by Wonil Choi <wonil22.choi@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/limits.h>
+#include <sys/smack.h>
+
+#ifdef DEBUG
+# define LOGINFO(fmt, arg...) printf(fmt, ##arg)
+#else
+# define LOGINFO(fmt, arg...)
+#endif
+
+void print_help(const char *cmd)
+{
+ printf("Usage: %s <INPUT FILE>\n", cmd);
+ printf(" INPUT FILE should be same format as generated by"
+ " chsmack.\n\n");
+ printf(" Ex) # chsmack /usr/bin/* > /tmp/rstsmack_input.txt\n");
+}
+
+static inline int abandonqm(char *label)
+{
+ int ret = 0;
+ /* ignore last character which must be a quotation mark */
+ ret = (int) strlen(label);
+ ret--;
+ if (ret > SMACK_LABEL_LEN || ret <= 0)
+ return -1;
+ label[ret] = '\0';
+ return 0;
+}
+
+static void set_label(const char *pathname, char *label, int type)
+{
+ int ret = -1;
+
+ if (abandonqm(label) == 0) {
+ ret = smack_lsetlabel(pathname, label, type);
+ if (ret < 0)
+ perror(pathname);
+ } else
+ fprintf(stderr, "The input file has wrong format, %s\n",
+ pathname);
+}
+
+static int parse_and_set(const char *srcfile)
+{
+ /* We assume the text format of input file is same as chsmack output */
+ FILE *fp;
+ int ret = 0;
+ char linebuf[PATH_MAX + 5 * SMACK_LABEL_LEN], pathname[PATH_MAX];
+ char label[SMACK_LABEL_LEN + 1];
+ char *plabel; /* pointer of beginning smack label */
+ fp = fopen(srcfile, "r");
+ if (fp == NULL)
+ return -1;
+
+ while (fgets(linebuf, sizeof(linebuf), fp)) {
+ plabel = strstr(linebuf, " access=");
+ if (plabel && linebuf != plabel) {
+ *plabel = '\0';
+ strncpy(pathname, linebuf, sizeof(pathname));
+ pathname[sizeof(pathname) - 1] = '\0';
+ plabel++;
+ } else {
+ linebuf[strlen(linebuf) - 1] = '\0';
+ LOGINFO("no label, set label: %s, access=\"_\"(floor)\n", linebuf);
+ strncpy(label, "_\"", SMACK_LABEL_LEN);
+ set_label(linebuf, label, SMACK_LABEL_ACCESS);
+ /* TODO: If file name contains " access=" then it would
+ * not be processed */
+ continue;
+ }
+
+ LOGINFO("set label: %s,", pathname);
+
+ ret = sscanf(plabel, "access=\"%s", label);
+ if (ret > 0) {
+ LOGINFO(" access: \"%s", label);
+ set_label(pathname, label, SMACK_LABEL_ACCESS);
+ plabel = plabel + sizeof(" access=\"") + strlen(label);
+ }
+
+ ret = sscanf(plabel, "execute=\"%s", label);
+ if (ret > 0) {
+ LOGINFO(", exec: \"%s", label);
+ set_label(pathname, label, SMACK_LABEL_EXEC);
+ plabel = plabel + sizeof(" execute=\"") + strlen(label);
+ }
+
+ ret = sscanf(plabel, "mmap=\"%s", label);
+ if (ret > 0) {
+ LOGINFO(", mmap: \"%s", label);
+ set_label(pathname, label, SMACK_LABEL_MMAP);
+ plabel = plabel + sizeof(" mmap=\"") + strlen(label);
+ }
+
+ ret = sscanf(plabel, "transmute=\"%s", label);
+ if (ret > 0) {
+ LOGINFO(", transmute: \"%s", label);
+ strncpy(label, "1\"", SMACK_LABEL_LEN);
+ set_label(pathname, label, SMACK_LABEL_TRANSMUTE);
+ }
+ LOGINFO("\n");
+
+ }
+ fclose(fp);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ print_help(argv[0]);
+ return -1;
+ }
+ if (parse_and_set(argv[1]) < 0) {
+ print_help(argv[0]);
+ return -1;
+ }
+ return 0;
+}