1 /*
2  * Copyright 2017, 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 #include <cutils/qtaguid.h>
18 
19 // #define LOG_NDEBUG 0
20 
21 #define LOG_TAG "qtaguid"
22 
23 #include <dlfcn.h>
24 #include <errno.h>
25 #include <inttypes.h>
26 
27 #include <log/log.h>
28 
29 struct netdHandler {
30     int (*netdTagSocket)(int, uint32_t, uid_t);
31     int (*netdUntagSocket)(int);
32 };
33 
stubTagSocket(int,uint32_t,uid_t)34 static int stubTagSocket(int, uint32_t, uid_t) {
35     return -EREMOTEIO;
36 }
37 
stubUntagSocket(int)38 static int stubUntagSocket(int) {
39     return -EREMOTEIO;
40 }
41 
initHandler(void)42 static netdHandler initHandler(void) {
43     const netdHandler stubHandler = { stubTagSocket, stubUntagSocket };
44 
45     void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
46     if (!netdClientHandle) {
47         ALOGE("Failed to open libnetd_client.so: %s", dlerror());
48         return stubHandler;
49     }
50 
51     netdHandler handler;
52     handler.netdTagSocket = (int (*)(int, uint32_t, uid_t))dlsym(netdClientHandle, "tagSocket");
53     if (!handler.netdTagSocket) {
54         ALOGE("load netdTagSocket handler failed: %s", dlerror());
55         return stubHandler;
56     }
57 
58     handler.netdUntagSocket = (int (*)(int))dlsym(netdClientHandle, "untagSocket");
59     if (!handler.netdUntagSocket) {
60         ALOGE("load netdUntagSocket handler failed: %s", dlerror());
61         return stubHandler;
62     }
63 
64     return handler;
65 }
66 
67 // The language guarantees that this object will be initialized in a thread-safe way.
getHandler()68 static const netdHandler& getHandler() {
69     static const netdHandler instance = initHandler();
70     return instance;
71 }
72 
qtaguid_tagSocket(int sockfd,int tag,uid_t uid)73 int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
74     ALOGV("Tagging socket %d with tag %u for uid %d", sockfd, tag, uid);
75     return getHandler().netdTagSocket(sockfd, tag, uid);
76 }
77 
qtaguid_untagSocket(int sockfd)78 int qtaguid_untagSocket(int sockfd) {
79     ALOGV("Untagging socket %d", sockfd);
80     return getHandler().netdUntagSocket(sockfd);
81 }
82