Possible regression by commit d96f27bf7cb9 ("libsemanage: Preserve file context and ownership in policy store")

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

When `selinux_restorecon()` is called first time, it creates a static
`fc_sehandle`. This semanage store handle is used later in `selabel_` functions and
left initialized to be used on the next call `selinux_restorecon()`. It
probably help with multiple sequential runs of `selinux_restorecon()`.

But since commit d96f27bf7cb9 ("libsemanage: Preserve file context and
ownership in policy store"), `selinux_restorecon` is also run internally
when policy store is changed by libsemanage. It means that if a user
tries to change file contexts and then relabel affected files,
`selinux_restorecon` uses semanage handle created before policy change
and therefore with old data, see the code [1]:


[root@localhost ~]# mkdir -p /data/test/subtest
[root@localhost ~]# gcc libsemanage-add-fcontext.c -lsemanage -lselinux
[root@localhost ~]# ./a.out 
Relabeled /data/test from unconfined_u:object_r:default_t:s0 to system_u:object_r:default_t:s0
Relabeled /data/test/subtest from unconfined_u:object_r:default_t:s0 to system_u:object_r:default_t:s0


Two ideas how to solve it I have:

- destroy fc_sehandle at the end selinux_restorecon() if the handle was
initialized there - could this affect the performance?

- document in man page this issue and suggest users to use

sehandle = selinux_restorecon_default_handle()
selinux_restorecon_set_sehandle(sehandle)

before any libsemanage store operation


I'm looking for any reasonable solution or ideas.


[1]
#include <selinux/restorecon.h>
#include <semanage/context_record.h>
#include <semanage/fcontext_record.h>
#include <semanage/fcontexts_local.h>
#include <semanage/handle.h>
#include <semanage/semanage.h>
#include <stdio.h>

int main(const int argc, const char **argv) {
  semanage_handle_t *sh = NULL;
  semanage_fcontext_t *fcontext;
  semanage_context_t *con;
  semanage_fcontext_key_t *k;

  int exist = 0;
  sh = semanage_handle_create();
  if (sh == NULL) {
    perror("Can't create semanage handle\n");
    return -1;
  }
  semanage_select_store(sh, "targeted", SEMANAGE_CON_DIRECT);
  if (semanage_is_managed(sh) < 0) {
    perror("Semanage store can't be accessed\n");
    return -1;
  }
    
  if (semanage_access_check(sh) < 0) {
    perror("Semanage access check failed\n");
    return -1;
  }
  if (semanage_connect(sh) < 0) {
    perror("Semanage connect failed\n");
    return -1;
  }
  if (semanage_begin_transaction(sh) < 0) {
    return -1;
  }

  semanage_fcontext_key_t *key_ptr;
  semanage_fcontext_key_create(sh, "/data/test(/.*)?", 0, &key_ptr);

  semanage_fcontext_t *fcontext_ptr;
  semanage_fcontext_create(sh, &fcontext_ptr);

  semanage_context_t *con_ptr;
  semanage_context_from_string(sh, "system_u:object_r:tmp_t:s0", &con_ptr);
  semanage_fcontext_set_expr(sh, fcontext_ptr, "/data/test(/.*)?");
  semanage_fcontext_set_type(fcontext_ptr, 0);
  semanage_fcontext_set_con(sh, fcontext_ptr, con_ptr);

  semanage_fcontext_modify_local(sh, key_ptr, fcontext_ptr);
  if (semanage_commit(sh) < 0) {
    perror("Semanage commit failed\n");
    return -1;
  }
  if (semanage_disconnect(sh) < 0) {
    perror("Semanage disconnect failed\n");
    return -1;
  }

  selinux_restorecon("/data/test", SELINUX_RESTORECON_RECURSE | SELINUX_RESTORECON_VERBOSE | SELINUX_RESTORECON_SET_SPECFILE_CTX);
}





[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux