| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 1 | /* Copyright 2008 The Android Open Source Project | 
 | 2 |  */ | 
 | 3 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 4 | #include <errno.h> | 
 | 5 | #include <fcntl.h> | 
| Elliott Hughes | 0b41ad5 | 2015-04-03 16:51:18 -0700 | [diff] [blame] | 6 | #include <inttypes.h> | 
| Mark Salyzyn | 13df5f5 | 2015-04-01 07:52:12 -0700 | [diff] [blame] | 7 | #include <stdio.h> | 
 | 8 | #include <stdlib.h> | 
 | 9 | #include <string.h> | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 10 |  | 
| Yifan Hong | 3f68cca | 2017-08-01 17:09:07 -0700 | [diff] [blame] | 11 | #include <cutils/android_filesystem_config.h> | 
| Arve Hjønnevåg | 6b9c6d2 | 2016-08-18 15:42:35 -0700 | [diff] [blame] | 12 | #include <cutils/multiuser.h> | 
 | 13 |  | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 14 | #include <selinux/android.h> | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 15 | #include <selinux/avc.h> | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 16 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 17 | #include "binder.h" | 
 | 18 |  | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 19 | #ifdef VENDORSERVICEMANAGER | 
 | 20 | #define LOG_TAG "VendorServiceManager" | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 21 | #else | 
 | 22 | #define LOG_TAG "ServiceManager" | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 23 | #endif | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 24 | #include <log/log.h> | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 25 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 26 | struct audit_data { | 
 | 27 |     pid_t pid; | 
 | 28 |     uid_t uid; | 
 | 29 |     const char *name; | 
 | 30 | }; | 
 | 31 |  | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 32 | const char *str8(const uint16_t *x, size_t x_len) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 33 | { | 
 | 34 |     static char buf[128]; | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 35 |     size_t max = 127; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 36 |     char *p = buf; | 
 | 37 |  | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 38 |     if (x_len < max) { | 
 | 39 |         max = x_len; | 
 | 40 |     } | 
 | 41 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 42 |     if (x) { | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 43 |         while ((max > 0) && (*x != '\0')) { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 44 |             *p++ = *x++; | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 45 |             max--; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 46 |         } | 
 | 47 |     } | 
 | 48 |     *p++ = 0; | 
 | 49 |     return buf; | 
 | 50 | } | 
 | 51 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 52 | int str16eq(const uint16_t *a, const char *b) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 53 | { | 
 | 54 |     while (*a && *b) | 
 | 55 |         if (*a++ != *b++) return 0; | 
 | 56 |     if (*a || *b) | 
 | 57 |         return 0; | 
 | 58 |     return 1; | 
 | 59 | } | 
 | 60 |  | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 61 | static char *service_manager_context; | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 62 | static struct selabel_handle* sehandle; | 
 | 63 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 64 | static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name) | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 65 | { | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 66 |     char *sctx = NULL; | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 67 |     const char *class = "service_manager"; | 
 | 68 |     bool allowed; | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 69 |     struct audit_data ad; | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 70 |  | 
 | 71 |     if (getpidcon(spid, &sctx) < 0) { | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 72 |         ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 73 |         return false; | 
 | 74 |     } | 
 | 75 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 76 |     ad.pid = spid; | 
 | 77 |     ad.uid = uid; | 
 | 78 |     ad.name = name; | 
 | 79 |  | 
 | 80 |     int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad); | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 81 |     allowed = (result == 0); | 
 | 82 |  | 
 | 83 |     freecon(sctx); | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 84 |     return allowed; | 
 | 85 | } | 
 | 86 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 87 | static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm) | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 88 | { | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 89 |     return check_mac_perms(spid, uid, service_manager_context, perm, NULL); | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 90 | } | 
 | 91 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 92 | static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name) | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 93 | { | 
 | 94 |     bool allowed; | 
 | 95 |     char *tctx = NULL; | 
 | 96 |  | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 97 |     if (!sehandle) { | 
 | 98 |         ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); | 
 | 99 |         abort(); | 
 | 100 |     } | 
 | 101 |  | 
 | 102 |     if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { | 
 | 103 |         ALOGE("SELinux: No match for %s in service_contexts.\n", name); | 
 | 104 |         return false; | 
 | 105 |     } | 
 | 106 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 107 |     allowed = check_mac_perms(spid, uid, tctx, perm, name); | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 108 |     freecon(tctx); | 
 | 109 |     return allowed; | 
 | 110 | } | 
 | 111 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 112 | static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 113 | { | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 114 |     const char *perm = "add"; | 
| Arve Hjønnevåg | 5fa90a0 | 2016-08-01 16:05:17 -0700 | [diff] [blame] | 115 |  | 
| Arve Hjønnevåg | 6b9c6d2 | 2016-08-18 15:42:35 -0700 | [diff] [blame] | 116 |     if (multiuser_get_app_id(uid) >= AID_APP) { | 
| Arve Hjønnevåg | 5fa90a0 | 2016-08-01 16:05:17 -0700 | [diff] [blame] | 117 |         return 0; /* Don't allow apps to register services */ | 
 | 118 |     } | 
 | 119 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 120 |     return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 121 | } | 
 | 122 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 123 | static int svc_can_list(pid_t spid, uid_t uid) | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 124 | { | 
 | 125 |     const char *perm = "list"; | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 126 |     return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0; | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 127 | } | 
 | 128 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 129 | static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 130 | { | 
 | 131 |     const char *perm = "find"; | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 132 |     return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 133 | } | 
 | 134 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 135 | struct svcinfo | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 136 | { | 
 | 137 |     struct svcinfo *next; | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 138 |     uint32_t handle; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 139 |     struct binder_death death; | 
 | 140 |     int allow_isolated; | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 141 |     size_t len; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 142 |     uint16_t name[0]; | 
 | 143 | }; | 
 | 144 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 145 | struct svcinfo *svclist = NULL; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 146 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 147 | struct svcinfo *find_svc(const uint16_t *s16, size_t len) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 148 | { | 
 | 149 |     struct svcinfo *si; | 
 | 150 |  | 
 | 151 |     for (si = svclist; si; si = si->next) { | 
 | 152 |         if ((len == si->len) && | 
 | 153 |             !memcmp(s16, si->name, len * sizeof(uint16_t))) { | 
 | 154 |             return si; | 
 | 155 |         } | 
 | 156 |     } | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 157 |     return NULL; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 158 | } | 
 | 159 |  | 
 | 160 | void svcinfo_death(struct binder_state *bs, void *ptr) | 
 | 161 | { | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 162 |     struct svcinfo *si = (struct svcinfo* ) ptr; | 
 | 163 |  | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 164 |     ALOGI("service '%s' died\n", str8(si->name, si->len)); | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 165 |     if (si->handle) { | 
 | 166 |         binder_release(bs, si->handle); | 
 | 167 |         si->handle = 0; | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 168 |     } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 169 | } | 
 | 170 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 171 | uint16_t svcmgr_id[] = { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 172 |     'a','n','d','r','o','i','d','.','o','s','.', | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 173 |     'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r' | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 174 | }; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 175 |  | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 176 |  | 
| Ian Pedowitz | d57d9b9 | 2016-02-19 08:34:43 +0000 | [diff] [blame] | 177 | uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 178 | { | 
| Nick Kralevich | b27bbd1 | 2015-03-05 10:58:40 -0800 | [diff] [blame] | 179 |     struct svcinfo *si = find_svc(s, len); | 
 | 180 |  | 
 | 181 |     if (!si || !si->handle) { | 
 | 182 |         return 0; | 
 | 183 |     } | 
 | 184 |  | 
 | 185 |     if (!si->allow_isolated) { | 
 | 186 |         // If this service doesn't allow access from isolated processes, | 
 | 187 |         // then check the uid to see if it is isolated. | 
 | 188 |         uid_t appid = uid % AID_USER; | 
 | 189 |         if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { | 
 | 190 |             return 0; | 
 | 191 |         } | 
 | 192 |     } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 193 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 194 |     if (!svc_can_find(s, len, spid, uid)) { | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 195 |         return 0; | 
 | 196 |     } | 
| Nick Kralevich | b27bbd1 | 2015-03-05 10:58:40 -0800 | [diff] [blame] | 197 |  | 
 | 198 |     return si->handle; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 199 | } | 
 | 200 |  | 
 | 201 | int do_add_service(struct binder_state *bs, | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 202 |                    const uint16_t *s, size_t len, | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 203 |                    uint32_t handle, uid_t uid, int allow_isolated, | 
 | 204 |                    pid_t spid) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 205 | { | 
 | 206 |     struct svcinfo *si; | 
| Serban Constantinescu | 3a345f0 | 2013-12-19 09:11:41 +0000 | [diff] [blame] | 207 |  | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 208 |     //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 209 |     //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid); | 
 | 210 |  | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 211 |     if (!handle || (len == 0) || (len > 127)) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 212 |         return -1; | 
 | 213 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 214 |     if (!svc_can_register(s, len, spid, uid)) { | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 215 |         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 216 |              str8(s, len), handle, uid); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 217 |         return -1; | 
 | 218 |     } | 
 | 219 |  | 
 | 220 |     si = find_svc(s, len); | 
 | 221 |     if (si) { | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 222 |         if (si->handle) { | 
 | 223 |             ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 224 |                  str8(s, len), handle, uid); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 225 |             svcinfo_death(bs, si); | 
 | 226 |         } | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 227 |         si->handle = handle; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 228 |     } else { | 
 | 229 |         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); | 
 | 230 |         if (!si) { | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 231 |             ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 232 |                  str8(s, len), handle, uid); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 233 |             return -1; | 
 | 234 |         } | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 235 |         si->handle = handle; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 236 |         si->len = len; | 
 | 237 |         memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); | 
 | 238 |         si->name[len] = '\0'; | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 239 |         si->death.func = (void*) svcinfo_death; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 240 |         si->death.ptr = si; | 
 | 241 |         si->allow_isolated = allow_isolated; | 
 | 242 |         si->next = svclist; | 
 | 243 |         svclist = si; | 
 | 244 |     } | 
 | 245 |  | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 246 |     binder_acquire(bs, handle); | 
 | 247 |     binder_link_to_death(bs, handle, &si->death); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 248 |     return 0; | 
 | 249 | } | 
 | 250 |  | 
 | 251 | int svcmgr_handler(struct binder_state *bs, | 
| Serban Constantinescu | bcf3888 | 2014-01-10 13:56:27 +0000 | [diff] [blame] | 252 |                    struct binder_transaction_data *txn, | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 253 |                    struct binder_io *msg, | 
 | 254 |                    struct binder_io *reply) | 
 | 255 | { | 
 | 256 |     struct svcinfo *si; | 
 | 257 |     uint16_t *s; | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 258 |     size_t len; | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 259 |     uint32_t handle; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 260 |     uint32_t strict_policy; | 
 | 261 |     int allow_isolated; | 
 | 262 |  | 
| Elliott Hughes | 0b41ad5 | 2015-04-03 16:51:18 -0700 | [diff] [blame] | 263 |     //ALOGI("target=%p code=%d pid=%d uid=%d\n", | 
 | 264 |     //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 265 |  | 
| Elliott Hughes | 0b41ad5 | 2015-04-03 16:51:18 -0700 | [diff] [blame] | 266 |     if (txn->target.ptr != BINDER_SERVICE_MANAGER) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 267 |         return -1; | 
 | 268 |  | 
| Arve Hjønnevåg | e5245cb | 2014-01-28 21:35:03 -0800 | [diff] [blame] | 269 |     if (txn->code == PING_TRANSACTION) | 
 | 270 |         return 0; | 
 | 271 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 272 |     // Equivalent to Parcel::enforceInterface(), reading the RPC | 
 | 273 |     // header with the strict mode policy mask and the interface name. | 
 | 274 |     // Note that we ignore the strict_policy and don't propagate it | 
 | 275 |     // further (since we do no outbound RPCs anyway). | 
 | 276 |     strict_policy = bio_get_uint32(msg); | 
 | 277 |     s = bio_get_string16(msg, &len); | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 278 |     if (s == NULL) { | 
 | 279 |         return -1; | 
 | 280 |     } | 
 | 281 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 282 |     if ((len != (sizeof(svcmgr_id) / 2)) || | 
 | 283 |         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 284 |         fprintf(stderr,"invalid id %s\n", str8(s, len)); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 285 |         return -1; | 
 | 286 |     } | 
 | 287 |  | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 288 |     if (sehandle && selinux_status_updated() > 0) { | 
| Kouji Shiotani | 61f8dfa | 2017-06-13 15:40:54 +0900 | [diff] [blame] | 289 | #ifdef VENDORSERVICEMANAGER | 
 | 290 |         struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle(); | 
 | 291 | #else | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 292 |         struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); | 
| Kouji Shiotani | 61f8dfa | 2017-06-13 15:40:54 +0900 | [diff] [blame] | 293 | #endif | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 294 |         if (tmp_sehandle) { | 
 | 295 |             selabel_close(sehandle); | 
 | 296 |             sehandle = tmp_sehandle; | 
 | 297 |         } | 
 | 298 |     } | 
 | 299 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 300 |     switch(txn->code) { | 
 | 301 |     case SVC_MGR_GET_SERVICE: | 
 | 302 |     case SVC_MGR_CHECK_SERVICE: | 
 | 303 |         s = bio_get_string16(msg, &len); | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 304 |         if (s == NULL) { | 
 | 305 |             return -1; | 
 | 306 |         } | 
| Ian Pedowitz | d57d9b9 | 2016-02-19 08:34:43 +0000 | [diff] [blame] | 307 |         handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid); | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 308 |         if (!handle) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 309 |             break; | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 310 |         bio_put_ref(reply, handle); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 311 |         return 0; | 
 | 312 |  | 
 | 313 |     case SVC_MGR_ADD_SERVICE: | 
 | 314 |         s = bio_get_string16(msg, &len); | 
| Nick Kralevich | 7d42a3c | 2014-07-12 16:34:01 -0700 | [diff] [blame] | 315 |         if (s == NULL) { | 
 | 316 |             return -1; | 
 | 317 |         } | 
| Serban Constantinescu | 5fb1b88 | 2014-01-30 14:07:34 +0000 | [diff] [blame] | 318 |         handle = bio_get_ref(msg); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 319 |         allow_isolated = bio_get_uint32(msg) ? 1 : 0; | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 320 |         if (do_add_service(bs, s, len, handle, txn->sender_euid, | 
 | 321 |             allow_isolated, txn->sender_pid)) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 322 |             return -1; | 
 | 323 |         break; | 
 | 324 |  | 
 | 325 |     case SVC_MGR_LIST_SERVICES: { | 
| Serban Constantinescu | 3a345f0 | 2013-12-19 09:11:41 +0000 | [diff] [blame] | 326 |         uint32_t n = bio_get_uint32(msg); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 327 |  | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 328 |         if (!svc_can_list(txn->sender_pid, txn->sender_euid)) { | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 329 |             ALOGE("list_service() uid=%d - PERMISSION DENIED\n", | 
 | 330 |                     txn->sender_euid); | 
 | 331 |             return -1; | 
 | 332 |         } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 333 |         si = svclist; | 
 | 334 |         while ((n-- > 0) && si) | 
 | 335 |             si = si->next; | 
 | 336 |         if (si) { | 
 | 337 |             bio_put_string16(reply, si->name); | 
 | 338 |             return 0; | 
 | 339 |         } | 
 | 340 |         return -1; | 
 | 341 |     } | 
 | 342 |     default: | 
 | 343 |         ALOGE("unknown code %d\n", txn->code); | 
 | 344 |         return -1; | 
 | 345 |     } | 
 | 346 |  | 
 | 347 |     bio_put_uint32(reply, 0); | 
 | 348 |     return 0; | 
 | 349 | } | 
 | 350 |  | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 351 |  | 
| Ian Pedowitz | d57d9b9 | 2016-02-19 08:34:43 +0000 | [diff] [blame] | 352 | static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len) | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 353 | { | 
| William Roberts | 8fb0f92 | 2015-10-01 22:02:15 -0700 | [diff] [blame] | 354 |     struct audit_data *ad = (struct audit_data *)data; | 
 | 355 |  | 
 | 356 |     if (!ad || !ad->name) { | 
 | 357 |         ALOGE("No service manager audit data"); | 
 | 358 |         return 0; | 
 | 359 |     } | 
 | 360 |  | 
 | 361 |     snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid); | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 362 |     return 0; | 
 | 363 | } | 
 | 364 |  | 
| Martijn Coenen | 69b0515 | 2017-03-21 10:00:38 -0700 | [diff] [blame] | 365 | int main(int argc, char** argv) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 366 | { | 
 | 367 |     struct binder_state *bs; | 
| Sandeep Patil | 93ba701 | 2016-12-27 12:40:45 -0800 | [diff] [blame] | 368 |     union selinux_callback cb; | 
| Martijn Coenen | 69b0515 | 2017-03-21 10:00:38 -0700 | [diff] [blame] | 369 |     char *driver; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 370 |  | 
| Martijn Coenen | 69b0515 | 2017-03-21 10:00:38 -0700 | [diff] [blame] | 371 |     if (argc > 1) { | 
 | 372 |         driver = argv[1]; | 
 | 373 |     } else { | 
 | 374 |         driver = "/dev/binder"; | 
 | 375 |     } | 
 | 376 |  | 
 | 377 |     bs = binder_open(driver, 128*1024); | 
| Serban Constantinescu | a44542c | 2014-01-30 15:16:45 +0000 | [diff] [blame] | 378 |     if (!bs) { | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 379 | #ifdef VENDORSERVICEMANAGER | 
 | 380 |         ALOGW("failed to open binder driver %s\n", driver); | 
 | 381 |         while (true) { | 
 | 382 |             sleep(UINT_MAX); | 
 | 383 |         } | 
 | 384 | #else | 
| Martijn Coenen | 69b0515 | 2017-03-21 10:00:38 -0700 | [diff] [blame] | 385 |         ALOGE("failed to open binder driver %s\n", driver); | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 386 | #endif | 
| Serban Constantinescu | a44542c | 2014-01-30 15:16:45 +0000 | [diff] [blame] | 387 |         return -1; | 
 | 388 |     } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 389 |  | 
 | 390 |     if (binder_become_context_manager(bs)) { | 
 | 391 |         ALOGE("cannot become context manager (%s)\n", strerror(errno)); | 
 | 392 |         return -1; | 
 | 393 |     } | 
 | 394 |  | 
| Sandeep Patil | 93ba701 | 2016-12-27 12:40:45 -0800 | [diff] [blame] | 395 |     cb.func_audit = audit_callback; | 
 | 396 |     selinux_set_callback(SELINUX_CB_AUDIT, cb); | 
 | 397 |     cb.func_log = selinux_log_callback; | 
 | 398 |     selinux_set_callback(SELINUX_CB_LOG, cb); | 
 | 399 |  | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 400 | #ifdef VENDORSERVICEMANAGER | 
 | 401 |     sehandle = selinux_android_vendor_service_context_handle(); | 
 | 402 | #else | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 403 |     sehandle = selinux_android_service_context_handle(); | 
| Martijn Coenen | 3136123 | 2017-03-31 16:12:12 -0700 | [diff] [blame] | 404 | #endif | 
| Stephen Smalley | bea0746 | 2015-06-03 09:25:37 -0400 | [diff] [blame] | 405 |     selinux_status_open(true); | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 406 |  | 
| Nick Kralevich | eb4d5cb | 2016-12-09 17:05:09 -0800 | [diff] [blame] | 407 |     if (sehandle == NULL) { | 
 | 408 |         ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); | 
 | 409 |         abort(); | 
 | 410 |     } | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 411 |  | 
| Nick Kralevich | eb4d5cb | 2016-12-09 17:05:09 -0800 | [diff] [blame] | 412 |     if (getcon(&service_manager_context) != 0) { | 
 | 413 |         ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); | 
 | 414 |         abort(); | 
| Riley Spahn | c67e630 | 2014-07-08 09:03:00 -0700 | [diff] [blame] | 415 |     } | 
 | 416 |  | 
| Riley Spahn | 69154df | 2014-06-05 11:07:18 -0700 | [diff] [blame] | 417 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 418 |     binder_loop(bs, svcmgr_handler); | 
| Serban Constantinescu | 9b738bb | 2014-01-10 15:48:29 +0000 | [diff] [blame] | 419 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 420 |     return 0; | 
 | 421 | } |