summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2013-05-13 12:37:04 -0400
committerStephen Smalley <sds@tycho.nsa.gov>2013-08-23 08:35:43 -0400
commit8348d279c7ce1a2453965ba7f05a7b818d58886c (patch)
tree5bf50a8793a7ad5f6f0bd475c54a72f49c37f7a9
parent5d8554323caddfa3ca02f31625ea72634312521f (diff)
downloadsystem_core-8348d279c7ce1a2453965ba7f05a7b818d58886c.tar.gz
system_core-8348d279c7ce1a2453965ba7f05a7b818d58886c.tar.bz2
system_core-8348d279c7ce1a2453965ba7f05a7b818d58886c.zip
Add support for socket security context specification.
Add an optional argument to the socket option for specifying a SELinux security context for the socket. Normally the socket security context is automatically computed from the service security context or set using the seclabel option, but this facility allows dealing with two scenarios that cannot be addressed using the existing mechanisms: 1) Use of logwrapper to wrap a service. In this case, init cannot determine the service security context as it does not directly execute it and we do not want logwrapper to run in the same domain as the service. 2) Situations where a service has multiple sockets and we want to label them distinctly. Change-Id: I7ae9088c326a2140e56a8044bfb21a91505aea11 Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
-rwxr-xr-xinit/init.c5
-rw-r--r--init/init.h1
-rw-r--r--init/init_parser.c4
-rwxr-xr-xinit/property_service.c2
-rw-r--r--init/readme.txt5
-rwxr-xr-xinit/util.c19
-rw-r--r--init/util.h2
7 files changed, 24 insertions, 14 deletions
diff --git a/init/init.c b/init/init.c
index 28d2863ab..0c9bf4a34 100755
--- a/init/init.c
+++ b/init/init.c
@@ -250,14 +250,12 @@ void service_start(struct service *svc, const char *dynamic_args)
for (ei = svc->envvars; ei; ei = ei->next)
add_environment(ei->name, ei->value);
- setsockcreatecon(scon);
-
for (si = svc->sockets; si; si = si->next) {
int socket_type = (
!strcmp(si->type, "stream") ? SOCK_STREAM :
(!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
int s = create_socket(si->name, socket_type,
- si->perm, si->uid, si->gid);
+ si->perm, si->uid, si->gid, si->socketcon ?: scon);
if (s >= 0) {
publish_socket(si->name, s);
}
@@ -265,7 +263,6 @@ void service_start(struct service *svc, const char *dynamic_args)
freecon(scon);
scon = NULL;
- setsockcreatecon(NULL);
if (svc->ioprio_class != IoSchedClass_NONE) {
if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
diff --git a/init/init.h b/init/init.h
index aa6a4ab02..3928d52b4 100644
--- a/init/init.h
+++ b/init/init.h
@@ -55,6 +55,7 @@ struct socketinfo {
uid_t uid;
gid_t gid;
int perm;
+ const char *socketcon;
};
struct svcenvinfo {
diff --git a/init/init_parser.c b/init/init_parser.c
index cce109386..616671a30 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -768,7 +768,7 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
svc->envvars = ei;
break;
}
- case K_socket: {/* name type perm [ uid gid ] */
+ case K_socket: {/* name type perm [ uid gid context ] */
struct socketinfo *si;
if (nargs < 4) {
parse_error(state, "socket option requires name, type, perm arguments\n");
@@ -791,6 +791,8 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
si->uid = decode_uid(args[4]);
if (nargs > 5)
si->gid = decode_uid(args[5]);
+ if (nargs > 6)
+ si->socketcon = args[6];
si->next = svc->sockets;
svc->sockets = si;
break;
diff --git a/init/property_service.c b/init/property_service.c
index 6c71807aa..27fb28490 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -554,7 +554,7 @@ void start_property_service(void)
/* Read persistent properties after all default values have been loaded. */
load_persistent_properties();
- fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);
+ fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0, NULL);
if(fd < 0) return;
fcntl(fd, F_SETFD, FD_CLOEXEC);
fcntl(fd, F_SETFL, O_NONBLOCK);
diff --git a/init/readme.txt b/init/readme.txt
index 7a5997d26..1e8c3920d 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -70,10 +70,13 @@ disabled
setenv <name> <value>
Set the environment variable <name> to <value> in the launched process.
-socket <name> <type> <perm> [ <user> [ <group> ] ]
+socket <name> <type> <perm> [ <user> [ <group> [ <context> ] ] ]
Create a unix domain socket named /dev/socket/<name> and pass
its fd to the launched process. <type> must be "dgram", "stream" or "seqpacket".
User and group default to 0.
+ Context is the SELinux security context for the socket.
+ It defaults to the service security context, as specified by seclabel or
+ computed based on the service executable file security context.
user <username>
Change to username before exec'ing this service.
diff --git a/init/util.c b/init/util.c
index 76af9e575..1820aa92b 100755
--- a/init/util.c
+++ b/init/util.c
@@ -83,11 +83,15 @@ unsigned int decode_uid(const char *s)
* daemon. We communicate the file descriptor's value via the environment
* variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
*/
-int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
+int create_socket(const char *name, int type, mode_t perm, uid_t uid,
+ gid_t gid, const char *socketcon)
{
struct sockaddr_un addr;
int fd, ret;
- char *secon;
+ char *filecon;
+
+ if (socketcon)
+ setsockcreatecon(socketcon);
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
@@ -95,6 +99,9 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
return -1;
}
+ if (socketcon)
+ setsockcreatecon(NULL);
+
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
@@ -106,11 +113,11 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
goto out_close;
}
- secon = NULL;
+ filecon = NULL;
if (sehandle) {
- ret = selabel_lookup(sehandle, &secon, addr.sun_path, S_IFSOCK);
+ ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
if (ret == 0)
- setfscreatecon(secon);
+ setfscreatecon(filecon);
}
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
@@ -120,7 +127,7 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
}
setfscreatecon(NULL);
- freecon(secon);
+ freecon(filecon);
chown(addr.sun_path, uid, gid);
chmod(addr.sun_path, perm);
diff --git a/init/util.h b/init/util.h
index 45905b618..39d6f5240 100644
--- a/init/util.h
+++ b/init/util.h
@@ -26,7 +26,7 @@ static const char *coldboot_done = "/dev/.coldboot_done";
int mtd_name_to_number(const char *name);
int create_socket(const char *name, int type, mode_t perm,
- uid_t uid, gid_t gid);
+ uid_t uid, gid_t gid, const char *socketcon);
void *read_file(const char *fn, unsigned *_sz);
time_t gettime(void);
unsigned int decode_uid(const char *s);