Home | History | Annotate | Download | only in libqtaguid
      1 /*
      2 ** Copyright 2011, The Android Open Source Project
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 // #define LOG_NDEBUG 0
     18 
     19 #define LOG_TAG "qtaguid"
     20 
     21 #include <errno.h>
     22 #include <fcntl.h>
     23 #include <inttypes.h>
     24 #include <pthread.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <unistd.h>
     28 
     29 #include <log/log.h>
     30 #include <qtaguid/qtaguid.h>
     31 
     32 static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
     33 static const int CTRL_MAX_INPUT_LEN = 128;
     34 
     35 /*
     36  * One per proccess.
     37  * Once the device is open, this process will have its socket tags tracked.
     38  * And on exit or untimely death, all socket tags will be removed.
     39  * A process can only open /dev/xt_qtaguid once.
     40  * It should not close it unless it is really done with all the socket tags.
     41  * Failure to open it will be visible when socket tagging will be attempted.
     42  */
     43 static int resTrackFd = -1;
     44 pthread_once_t resTrackInitDone = PTHREAD_ONCE_INIT;
     45 
     46 /* Only call once per process. */
     47 void legacy_resTrack(void) {
     48     resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY | O_CLOEXEC));
     49 }
     50 
     51 /*
     52  * Returns:
     53  *   0 on success.
     54  *   -errno on failure.
     55  */
     56 static int write_ctrl(const char* cmd) {
     57     int fd, res, savedErrno;
     58 
     59     ALOGV("write_ctrl(%s)", cmd);
     60 
     61     fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY | O_CLOEXEC));
     62     if (fd < 0) {
     63         return -errno;
     64     }
     65 
     66     res = TEMP_FAILURE_RETRY(write(fd, cmd, strlen(cmd)));
     67     if (res < 0) {
     68         savedErrno = errno;
     69     } else {
     70         savedErrno = 0;
     71     }
     72     if (res < 0) {
     73         // ALOGV is enough because all the callers also log failures
     74         ALOGV("Failed write_ctrl(%s) res=%d errno=%d", cmd, res, savedErrno);
     75     }
     76     close(fd);
     77     return -savedErrno;
     78 }
     79 
     80 int legacy_tagSocket(int sockfd, int tag, uid_t uid) {
     81     char lineBuf[CTRL_MAX_INPUT_LEN];
     82     int res;
     83     uint64_t kTag = ((uint64_t)tag << 32);
     84 
     85     pthread_once(&resTrackInitDone, legacy_resTrack);
     86 
     87     snprintf(lineBuf, sizeof(lineBuf), "t %d %" PRIu64 " %d", sockfd, kTag, uid);
     88 
     89     ALOGV("Tagging socket %d with tag %" PRIx64 "{%u,0} for uid %d", sockfd, kTag, tag, uid);
     90 
     91     res = write_ctrl(lineBuf);
     92     if (res < 0) {
     93         ALOGI("Tagging socket %d with tag %" PRIx64 "(%d) for uid %d failed errno=%d", sockfd, kTag,
     94               tag, uid, res);
     95     }
     96 
     97     return res;
     98 }
     99 
    100 int legacy_untagSocket(int sockfd) {
    101     char lineBuf[CTRL_MAX_INPUT_LEN];
    102     int res;
    103 
    104     ALOGV("Untagging socket %d", sockfd);
    105 
    106     snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
    107     res = write_ctrl(lineBuf);
    108     if (res < 0) {
    109         ALOGI("Untagging socket %d failed errno=%d", sockfd, res);
    110     }
    111 
    112     return res;
    113 }
    114 
    115 int legacy_setCounterSet(int counterSetNum, uid_t uid) {
    116     char lineBuf[CTRL_MAX_INPUT_LEN];
    117     int res;
    118 
    119     ALOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
    120 
    121     snprintf(lineBuf, sizeof(lineBuf), "s %d %d", counterSetNum, uid);
    122     res = write_ctrl(lineBuf);
    123     return res;
    124 }
    125 
    126 int legacy_deleteTagData(int tag, uid_t uid) {
    127     char lineBuf[CTRL_MAX_INPUT_LEN];
    128     int cnt = 0, res = 0;
    129     uint64_t kTag = (uint64_t)tag << 32;
    130 
    131     ALOGV("Deleting tag data with tag %" PRIx64 "{%d,0} for uid %d", kTag, tag, uid);
    132 
    133     pthread_once(&resTrackInitDone, legacy_resTrack);
    134 
    135     snprintf(lineBuf, sizeof(lineBuf), "d %" PRIu64 " %d", kTag, uid);
    136     res = write_ctrl(lineBuf);
    137     if (res < 0) {
    138         ALOGI("Deleting tag data with tag %" PRIx64 "/%d for uid %d failed with cnt=%d errno=%d",
    139               kTag, tag, uid, cnt, errno);
    140     }
    141 
    142     return res;
    143 }
    144