• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <string.h>
3 #include <sys/capability.h>
4 
5 #include <android-base/logging.h>
6 #include <selinux/android.h>
7 
8 uint8_t kBase64Map[256] = {
9     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
10     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
11     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
12     255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
13      52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
14     255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
15       7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
16      19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
17     255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
18      37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
19      49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
20     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
21     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
22     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
23     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
24     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
25     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
26     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
27     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
28     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
29     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
30     255, 255, 255, 255
31 };
32 
DecodeBase64(const char * src,size_t * dst_size)33 uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
34     CHECK(dst_size != nullptr);
35     std::vector<uint8_t> tmp;
36     uint32_t t = 0, y = 0;
37     int g = 3;
38     for (size_t i = 0; src[i] != '\0'; ++i) {
39         uint8_t c = kBase64Map[src[i] & 0xFF];
40         if (c == 255) continue;
41         // the final = symbols are read and used to trim the remaining bytes
42         if (c == 254) {
43             c = 0;
44             // prevent g < 0 which would potentially allow an overflow later
45             if (--g < 0) {
46                 *dst_size = 0;
47                 return nullptr;
48             }
49         } else if (g != 3) {
50             // we only allow = to be at the end
51             *dst_size = 0;
52             return nullptr;
53         }
54         t = (t << 6) | c;
55         if (++y == 4) {
56             tmp.push_back((t >> 16) & 255);
57             if (g > 1) {
58                 tmp.push_back((t >> 8) & 255);
59             }
60             if (g > 2) {
61                 tmp.push_back(t & 255);
62             }
63             y = t = 0;
64         }
65     }
66     if (y != 0) {
67         *dst_size = 0;
68         return nullptr;
69     }
70     std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
71     *dst_size = tmp.size();
72     std::copy(tmp.begin(), tmp.end(), dst.get());
73     return dst.release();
74 }
75 
WriteBase64ToFile(const char * base64,const std::string & file,uid_t uid,gid_t gid,int mode)76 bool WriteBase64ToFile(const char* base64, const std::string& file,
77         uid_t uid, gid_t gid, int mode) {
78     CHECK(base64 != nullptr);
79     size_t length;
80     std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
81     CHECK(bytes != nullptr);
82 
83 
84     int fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
85 
86     if (fd < 0) {
87         PLOG(ERROR) << "Could not open file " << file;
88         return false;
89     }
90 
91     size_t wrote = 0;
92     while (wrote < length) {
93         ssize_t cur = write(fd, bytes.get() + wrote, length - wrote);
94         if (cur == -1) {
95             PLOG(ERROR) << "Could not write file " << file;
96             return false;
97         }
98         wrote += cur;
99     }
100 
101     if (::chown(file.c_str(), uid, gid) != 0) {
102         PLOG(ERROR) << "Could not chown file " << file;
103         return false;
104     }
105     if (::chmod(file.c_str(), mode) != 0) {
106         PLOG(ERROR) << "Could not chmod file " << file;
107         return false;
108     }
109     return true;
110 }
111 
112 // TODO(calin): fix dexopt drop_capabilities and move to general utils (b/69678790).
DropCapabilities(uid_t uid,gid_t gid)113 bool DropCapabilities(uid_t uid, gid_t gid) {
114     if (setgid(gid) != 0) {
115         PLOG(ERROR) << "setgid failed: " <<  gid;
116         return false;
117     }
118     if (setuid(uid) != 0) {
119         PLOG(ERROR) << "setuid failed: " <<  uid;
120         return false;
121     }
122     // drop capabilities
123     struct __user_cap_header_struct capheader;
124     struct __user_cap_data_struct capdata[2];
125     memset(&capheader, 0, sizeof(capheader));
126     memset(&capdata, 0, sizeof(capdata));
127     capheader.version = _LINUX_CAPABILITY_VERSION_3;
128     if (capset(&capheader, &capdata[0]) < 0) {
129         PLOG(ERROR) << "capset failed";
130         return false;
131     }
132 
133     return true;
134 }
135