[apparmor] [PATCH 2/5] Add the ability to read proc attr interfaces

John Johansen john.johansen at canonical.com
Thu Jul 21 18:16:35 UTC 2011


Signed-off-by: John Johansen <john.johansen at canonical.com>
---
 libraries/libapparmor/src/apparmor.h          |    5 +
 libraries/libapparmor/src/kernel_interface.c  |  131 +++++++++++++++++++++++++
 libraries/libapparmor/src/libapparmor.map     |    3 +
 libraries/libapparmor/swig/SWIG/libapparmor.i |    4 +-
 4 files changed, 142 insertions(+), 1 deletions(-)

diff --git a/libraries/libapparmor/src/apparmor.h b/libraries/libapparmor/src/apparmor.h
index 4ae0a03..b0e6a65 100644
--- a/libraries/libapparmor/src/apparmor.h
+++ b/libraries/libapparmor/src/apparmor.h
@@ -34,6 +34,11 @@ extern int aa_change_onexec(const char *profile);
 extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
 extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
 
+/* Protypes for introspecting task confinement */
+extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
+			      char **mode);
+extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
+
 #define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
 #define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
 #define __macroarg_count2(_,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,n,Y...) n
diff --git a/libraries/libapparmor/src/kernel_interface.c b/libraries/libapparmor/src/kernel_interface.c
index 0e61065..67356dc 100644
--- a/libraries/libapparmor/src/kernel_interface.c
+++ b/libraries/libapparmor/src/kernel_interface.c
@@ -54,6 +54,137 @@ static char *procattr_path(pid_t pid, const char *attr)
 	return NULL;
 }
 
+/**
+ * aa_getprocattr_raw - get the contents of @attr for @tid into @buf
+ * @tid: tid of task to query
+ * @attr: which /proc/<tid>/attr/<attr> to query
+ * @buf: buffer to store the result in
+ * @len: size of the buffer
+ * @mode: if set will point to mode string within buffer if it is present
+ *
+ * Returns: size of data read or -1 on error, and sets errno
+ */
+int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
+		       char **mode)
+{
+	int rc = -1;
+	int fd, ret;
+	char *tmp = NULL;
+	int size = 0;
+
+	if (!buf || len <= 0) {
+		errno = EINVAL;
+		goto out;
+	}
+
+	tmp = procattr_path(tid, attr);
+	if (!tmp)
+		goto out;
+
+	fd = open(tmp, O_RDONLY);
+	free(tmp);
+	if (fd == -1) {
+		goto out;
+	}
+
+	tmp = buf;
+	do {
+		ret = read(fd, tmp, len);
+		if (ret <= 0)
+			break;
+		tmp += ret;
+		size += ret;
+		len -= ret;
+		if (len < 0) {
+			errno = ENAMETOOLONG;
+			goto out2;
+		}
+	} while (ret > 0);
+
+	if (ret < 0) {
+		int saved;
+		if (ret != -1) {
+			errno = EPROTO;
+		}
+		saved = errno;
+		(void)close(fd);
+		errno = saved;
+		goto out;
+	} else if (size > 0 && buf[size - 1] != 0) {
+		/* check for null termination */
+		if (buf[size - 1] == '\n') {
+			buf[size - 1] = 0;
+		} else if (len == 0) {
+			errno = ENAMETOOLONG;
+			goto out2;
+		} else {
+			buf[size] = 0;
+			size++;
+		}
+
+		/*
+		 * now separate the mode.  If we don't find it just
+		 * return NULL
+		 */
+		if (mode)
+			*mode = NULL;
+		if (strcmp(buf, "unconfined") != 0 &&
+		    size > 4 && buf[size - 2] == ')') {
+			int pos = size - 3;
+			while (pos > 0 &&
+			       !(buf[pos] == ' ' && buf[pos + 1] == '('))
+				pos--;
+			if (pos > 0) {
+				buf[pos] = 0; /* overwrite ' ' */
+				buf[size - 2] = 0; /* overwrite trailing ) */
+				if (mode)
+					*mode = &buf[pos + 2]; /* skip '(' */
+			}
+		}
+	}
+	rc = size;
+
+out2:
+	(void)close(fd);
+out:
+	return rc;
+}
+
+#define INITIAL_GUESS_SIZE 128
+
+/**
+ * aa_getprocattr - get the contents of @attr for @tid into @buf
+ * @tid: tid of task to query
+ * @attr: which /proc/<tid>/attr/<attr> to query
+ * @buf: allocated buffer the result is stored in
+ * @mode: if set will point to mode string within buffer if it is present
+ *
+ * Returns: size of data read or -1 on error, and sets errno
+ */
+int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode)
+{
+	int rc, size = INITIAL_GUESS_SIZE/2;
+	char *buffer = NULL;
+
+	do {
+		size <<= 1;
+		buffer = realloc(buffer, size);
+		if (!buffer)
+			return -1;
+		memset(buffer, 0, size);
+
+		rc = aa_getprocattr_raw(tid, attr, buffer, size, mode);
+	} while (rc == -1 && errno == ENAMETOOLONG);
+
+	if (rc == -1) {
+		free(buffer);
+		size = -1;
+	} else
+		*buf = buffer;
+
+	return size;
+}
+
 static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
 {
 	int rc = -1;
diff --git a/libraries/libapparmor/src/libapparmor.map b/libraries/libapparmor/src/libapparmor.map
index c56cb86..a0c1a25 100644
--- a/libraries/libapparmor/src/libapparmor.map
+++ b/libraries/libapparmor/src/libapparmor.map
@@ -23,6 +23,9 @@ APPARMOR_1.1 {
         aa_change_onexec;
         parse_record;
         free_record;
+        aa_getprocattr_raw;
+        aa_getprocattr;
+
   local:
 	*;
 } APPARMOR_1.0;
diff --git a/libraries/libapparmor/swig/SWIG/libapparmor.i b/libraries/libapparmor/swig/SWIG/libapparmor.i
index 1f2ede3..9c39359 100644
--- a/libraries/libapparmor/swig/SWIG/libapparmor.i
+++ b/libraries/libapparmor/swig/SWIG/libapparmor.i
@@ -18,4 +18,6 @@ extern int aa_change_profile(const char *profile);
 extern int aa_change_onexec(const char *profile);
 extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
 extern int aa_change_hat_vargs(unsigned long token, int count, ...);
-
+extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
+			      char **mode);
+extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
-- 
1.7.5.4




More information about the AppArmor mailing list