summaryrefslogtreecommitdiffstats
path: root/libcutils/qtaguid.c
diff options
context:
space:
mode:
authorJP Abgrall <jpa@google.com>2011-09-09 15:02:08 -0700
committerJP Abgrall <jpa@google.com>2011-09-14 15:00:40 -0700
commit243123fb41d7d2981116bd5d11ba168b127d68e9 (patch)
tree36a920714511c87e83994c473733c64ed07dcc08 /libcutils/qtaguid.c
parentaa61854645ffed8595507463820e81aa0aa8f2fd (diff)
downloadsystem_core-243123fb41d7d2981116bd5d11ba168b127d68e9.zip
system_core-243123fb41d7d2981116bd5d11ba168b127d68e9.tar.gz
system_core-243123fb41d7d2981116bd5d11ba168b127d68e9.tar.bz2
libcutils: qtaguid: Support new functions, add tag resource tracking.
* Add support for deleteTagData(tag, uid) setCounterSet(counterSetNum, uid) setPacifier(on) * Add resource tracking (If only kernel process termination had a hook) Because the xt_qtaguid netfilter module needs to keep track of tagged sockets, it needs a way to know when the process owning the socket has died. Normally the app will untag the sockets. But not on crash. So the process opens the qtaguid misc dev, which is closed on crash, at which point the xt_qtaguid can force-untag the processes sockets, and thus allowing their refcount to go down and release them. * Add pacifier support Add function to enable/disable pacification of the xt_qtaguid kernel module. (mostly for debugging) Change-Id: I7f2228e65208046dd37ec1c7407ee307d5ba9b99
Diffstat (limited to 'libcutils/qtaguid.c')
-rw-r--r--libcutils/qtaguid.c154
1 files changed, 132 insertions, 22 deletions
diff --git a/libcutils/qtaguid.c b/libcutils/qtaguid.c
index 218a21f..7e1c42b 100644
--- a/libcutils/qtaguid.c
+++ b/libcutils/qtaguid.c
@@ -24,44 +24,154 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <pthread.h>
-extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
- char lineBuf[128];
- int fd, cnt = 0, res = 0;
- uint64_t kTag = (uint64_t)tag << 32;
- snprintf(lineBuf, sizeof(lineBuf), "t %d %llu %d", sockfd, kTag, uid);
+static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
+static const int CTRL_MAX_INPUT_LEN = 128;
+static const char *GLOBAL_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/passive";
+static const char *TAG_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/tag_tracking_passive";
+
+/*
+ * One per proccess.
+ * Once the device is open, this process will have its socket tags tracked.
+ * And on exit or untimely death, all socket tags will be removed.
+ * A process can only open /dev/xt_qtaguid once.
+ * It should not close it unless it is really done with all the socket tags.
+ * Failure to open it will be visible when socket tagging will be attempted.
+ */
+static int resTrackFd = -1;
+pthread_once_t resTrackInitDone = PTHREAD_ONCE_INIT;
+
+/* Only call once per process. */
+void qtaguid_resTrack(void) {
+ resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY));
+ if (resTrackFd >=0) {
+ TEMP_FAILURE_RETRY(fcntl(resTrackFd, F_SETFD, FD_CLOEXEC));
+ }
+}
- LOGI("Tagging socket %d with tag %llx(%d) for uid %d", sockfd, kTag, tag, uid);
- fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY);
+/*
+ * Returns:
+ * 0 on success.
+ * -errno on failure.
+ */
+static int write_ctrl(const char *cmd) {
+ int fd, res, savedErrno;
+
+ LOGI("write_ctrl(%s)", cmd);
+
+ fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY));
if (fd < 0) {
return -errno;
}
- cnt = write(fd, lineBuf, strlen(lineBuf));
- if (cnt < 0) {
- res = -errno;
+ res = TEMP_FAILURE_RETRY(write(fd, cmd, strlen(cmd)));
+ if (res < 0) {
+ savedErrno = errno;
+ } else {
+ savedErrno = 0;
+ }
+ if (res < 0) {
+ LOGI("Failed write_ctrl(%s) res=%d errno=%d", cmd, res, savedErrno);
}
-
close(fd);
+ return -savedErrno;
+}
+
+static int write_param(const char *param_path, const char *value) {
+ int param_fd;
+ int res;
+
+ param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY));
+ if (param_fd < 0) {
+ return -errno;
+ }
+ res = TEMP_FAILURE_RETRY(write(param_fd, value, strlen(value)));
+ if (res < 0) {
+ return -errno;
+ }
+ close(param_fd);
+ return 0;
+}
+
+int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
+ char lineBuf[CTRL_MAX_INPUT_LEN];
+ int res;
+ /* Doing java-land a favor, enforcing "long" */
+ uint64_t kTag = ((uint64_t)tag << 32) & ~(1LLU<<63);
+
+
+ pthread_once(&resTrackInitDone, qtaguid_resTrack);
+
+ snprintf(lineBuf, sizeof(lineBuf), "t %d %llu %d", sockfd, kTag, uid);
+
+ LOGI("Tagging socket %d with tag %llx{%u,0} for uid %d", sockfd, kTag, tag, uid);
+
+ res = write_ctrl(lineBuf);
+ if (res < 0) {
+ LOGI("Tagging socket %d with tag %llx(%d) for uid %d failed errno=%d",
+ sockfd, kTag, tag, uid, res);
+ }
+
return res;
}
-extern int qtaguid_untagSocket(int sockfd) {
- char lineBuf[128];
- int fd, cnt = 0, res = 0;
- snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
+int qtaguid_untagSocket(int sockfd) {
+ char lineBuf[CTRL_MAX_INPUT_LEN];
+ int res;
LOGI("Untagging socket %d", sockfd);
- fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY);
- if (fd < 0) {
- return -errno;
+
+ snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
+ res = write_ctrl(lineBuf);
+ if (res < 0) {
+ LOGI("Untagging socket %d failed errno=%d", sockfd, res);
}
- cnt = write(fd, lineBuf, strlen(lineBuf));
- if (cnt < 0) {
- res = -errno;
+ return res;
+}
+
+int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
+ char lineBuf[CTRL_MAX_INPUT_LEN];
+ int res;
+
+ LOGI("Setting counters to set %d for uid %d", counterSetNum, uid);
+
+ snprintf(lineBuf, sizeof(lineBuf), "s %d %d", counterSetNum, uid);
+ res = write_ctrl(lineBuf);
+ return res;
+}
+
+int qtaguid_deleteTagData(int tag, uid_t uid) {
+ char lineBuf[CTRL_MAX_INPUT_LEN];
+ int fd, cnt = 0, res = 0;
+ uint64_t kTag = (uint64_t)tag << 32;
+
+ LOGI("Deleting tag data with tag %llx{%d,0} for uid %d", kTag, tag, uid);
+
+ pthread_once(&resTrackInitDone, qtaguid_resTrack);
+
+ snprintf(lineBuf, sizeof(lineBuf), "d %llu %d", kTag, uid);
+ res = write_ctrl(lineBuf);
+ if (res < 0) {
+ LOGI("Deleteing tag data with tag %llx/%d for uid %d failed with cnt=%d errno=%d",
+ kTag, tag, uid, cnt, errno);
}
- close(fd);
return res;
}
+
+int qtaguid_setPacifier(int on) {
+ int param_fd;
+ int res;
+ const char *value;
+
+ value = on ? "Y" : "N";
+ if (write_param(GLOBAL_PACIFIER_PARAM, value) < 0) {
+ return -errno;
+ }
+ if (write_param(TAG_PACIFIER_PARAM, value) < 0) {
+ return -errno;
+ }
+ return 0;
+}