Fix labelling of files of widgets 62/24962/2
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 10 Jul 2020 11:18:47 +0000 (13:18 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Sat, 11 Jul 2020 16:44:19 +0000 (18:44 +0200)
Before that change any application could browse
content of other application.

This change fixes that unintended behaviour by setting
the installed files as private to the application.

This affects the Smack labels of the files that after
the change become the label of the application.

Conversely, it will now be necessarily to explicit
shared files. It happens in situation of resource
widgets, the one that provide a binding using the
feature urn:AGL:widget:provided-binding in config.xml.

The typical example is the widget for testing: afbtest.
The exported binding must be accessible by its clients.
But because it also use files that it provides, these
files must also be accessible by clients.

For that reason, the feature urn:AGL:widget:public-files
is introduced to config files, allowing a widget to make
part of its installed files public.

The installation logic is changed to handle correctly the
security manager that applies rights of directories to
files it contains. So the declaring directories and files
using the order of increasing path length ensures that
the expected rights are applied.

Bug-AGL: SPEC-3489

Change-Id: I933446a8c155a03d9b66767f1dda63aeaeb21eb1
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/secmgr-wrap.c
src/secmgr-wrap.h
src/wgtpkg-install.c

index 63704ef..83a2660 100644 (file)
@@ -117,7 +117,7 @@ static int addpath(const char *pathname, enum app_install_path_type type)
 
 int secmgr_path_public_read_only(const char *pathname)
 {
-       return addpath(pathname, SECURITY_MANAGER_PATH_RO);
+       return addpath(pathname, SECURITY_MANAGER_PATH_PUBLIC_RO);
 }
 
 int secmgr_path_read_only(const char *pathname)
@@ -130,6 +130,11 @@ int secmgr_path_read_write(const char *pathname)
        return addpath(pathname, SECURITY_MANAGER_PATH_RW);
 }
 
+int secmgr_path_private(const char *pathname)
+{
+       return addpath(pathname, SECURITY_MANAGER_PATH_PRIVATE);
+}
+
 int secmgr_prepare_exec(const char *appid)
 {
        return retcode(security_manager_prepare_app(appid));
index 2d16a8d..608ed8d 100644 (file)
@@ -24,5 +24,6 @@ extern int secmgr_permit(const char *permission);
 extern int secmgr_path_public_read_only(const char *pathname);
 extern int secmgr_path_read_only(const char *pathname);
 extern int secmgr_path_read_write(const char *pathname);
+extern int secmgr_path_private(const char *pathname);
 
 extern int secmgr_prepare_exec(const char *appid);
index c7de1f8..03cd78f 100644 (file)
@@ -485,22 +485,60 @@ static int install_file_properties(const struct wgt_desc *desc)
        return rc;
 }
 
+static int is_path_public(const char *path, const struct wgt_desc *desc)
+{
+       const struct wgt_desc_icon *icon;
+       const struct wgt_desc_feature *feat;
+       const struct wgt_desc_param *param;
+       size_t len;
+
+       /* icons are public */
+       icon = desc->icons;
+       while (icon != NULL) {
+               len = strlen(icon->src);
+               if (!memcmp(path, icon->src, len) && (path[len] == 0 || path[len] == '/'))
+                       return 1;
+               icon = icon->next;
+       }
+
+       /* provided bindings are public */
+       feat = desc->features;
+       while (feat != NULL) {
+               if (strcasecmp(feat->name, "urn:AGL:widget:provided-binding") == 0
+                || strcasecmp(feat->name, "urn:AGL:widget:public-files") == 0) {
+                       param = feat->params;
+                       while(param != NULL) {
+                               if (strcmp(param->value, path) == 0)
+                                       return 1;
+                               param = param->next;
+                       }
+               }
+               feat = feat->next;
+       }
+
+       /* otherwise no */
+       return 0;
+}
+
 static int install_security(const struct wgt_desc *desc)
 {
        char path[PATH_MAX], *head;
-       const char *icon, *perm;
-       int rc;
-       unsigned int i, n, len, lic, lf;
+       const char *perm;
+       int rc, public;
+       unsigned int i, n, len, lf, j;
        struct filedesc *f;
-
+       struct pathent {
+               struct pathent *next;
+               unsigned int len;
+               int public;
+               char name[];
+       } *pe0, *pe2, *ppe;
+
+       pe0 = NULL;
        rc = secmgr_init(desc->id);
        if (rc)
                goto error;
 
-       rc = secmgr_path_public_read_only(workdir);
-       if (rc)
-               goto error2;
-
        /* instal the files */
        head = stpcpy(path, workdir);
        assert(head < path + sizeof path);
@@ -512,23 +550,78 @@ static int install_security(const struct wgt_desc *desc)
        }
        len--;
        *head++ = '/';
-       icon = desc->icons ? desc->icons->src : NULL;
-       lic = (unsigned)(icon ? strlen(icon) : 0);
+
+       /* build root entry */
+       pe0 = malloc(1 + sizeof *pe0);
+       if (pe0 == NULL)
+               goto error2;
+       pe0->next = NULL;
+       pe0->len = 0;
+       pe0->public = 0;
+       pe0->name[0] = 0;
+
+       /* build list of entries */
        n = file_count();
-       i = 0;
-       while(i < n) {
-               f = file_of_index(i++);
-               lf = (unsigned)strlen(f->name);
-               if (lf >= len) {
-                       ERROR("path too long in install_security");
-                       errno = ENAMETOOLONG;
-                       goto error2;
+       for (i = 0 ; i < n ; i++) {
+               f = file_of_index(i);
+               public = is_path_public(f->name, desc);
+               pe0->public |= public;
+               lf = j = 0;
+               while(f->name[j] == '/')
+                       j++;
+               while (f->name[j] != 0) {
+                       /* copy next entry of the path */
+                       while(f->name[j] && f->name[j] != '/') {
+                               if (lf + 1 >= len) {
+                                       ERROR("path too long in install_security");
+                                       errno = ENAMETOOLONG;
+                                       goto error2;
+                               }
+                               head[lf++] = f->name[j++];
+                       }
+                       head[lf] = 0;
+
+                       /* search if it already exists */
+                       ppe = pe0;
+                       pe2 = pe0->next;
+                       while (pe2 != NULL && pe2->len < lf) {
+                               ppe = pe2;
+                               pe2 = pe2->next;
+                       }
+                       while (pe2 != NULL && pe2->len == lf && strcmp(head, pe2->name)) {
+                               ppe = pe2;
+                               pe2 = pe2->next;
+                       }
+
+                       if (pe2 != NULL && pe2->len == lf)
+                               /* existing, update public status */
+                               pe2->public |= public;
+                       else {
+                               /* not existing, create it */
+                               pe2 = malloc(lf + 1 + sizeof *pe2);
+                               if (pe2 == NULL)
+                                       goto error2;
+                               pe2->next = ppe->next;
+                               pe2->len = lf;
+                               pe2->public = public;
+                               memcpy(pe2->name, head, 1 + lf);
+                               ppe->next = pe2;
+                       }
+
+                       /* prepare next path entry */
+                       head[lf++] = '/';       
+                       while(f->name[j] == '/')
+                               j++;
                }
-               strcpy(head, f->name);
-               if (lf <= lic && icon && !memcmp(f->name, icon, lf) && (!f->name[lf] || f->name[lf] == '/'))
+       }
+
+       /* set the path entries */
+       for (pe2 = pe0 ; pe2 != NULL ; pe2 = pe2->next) {
+               strcpy(head, pe2->name);
+               if (pe2->public)
                        rc = secmgr_path_public_read_only(path);
                else
-                       rc = secmgr_path_read_only(path);
+                       rc = secmgr_path_private(path);
                if (rc)
                        goto error2;
        }
@@ -554,11 +647,19 @@ static int install_security(const struct wgt_desc *desc)
        }
 
        rc = secmgr_install();
-       return rc;
+       goto end;
 error2:
        secmgr_cancel();
 error:
-       return -1;
+       rc = -1;
+end:
+       /* free memory of path entries */
+       while (pe0 != NULL) {
+               ppe = pe0;
+               pe0 = pe0->next;
+               free(ppe);
+       }
+       return rc;
 }
 
 /* install the widget of the file */