libselinux: move realpath helper to matchpathcon library

Instead of only doing path simplification and symlink following for the
matchpathcon helper instead do it in the library potion.  This was an
issue when in python some called selinux.matchpatchcon("//lib64", 0) and
got the wrong answer (because the // wasn't being dealt with)

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
Eric Paris 2011-08-17 11:24:25 -04:00
parent 57c6012f86
commit 7df397d3d9
2 changed files with 73 additions and 72 deletions

View File

@ -5,6 +5,7 @@
#include "selinux_internal.h"
#include "label_internal.h"
#include "callbacks.h"
#include <limits.h>
static __thread struct selabel_handle *hnd;
@ -337,14 +338,82 @@ void matchpathcon_fini(void)
}
}
int matchpathcon(const char *name, mode_t mode, security_context_t * con)
/*
* We do not want to resolve a symlink to a real path if it is the final
* component of the name. Thus we split the pathname on the last "/" and
* determine a real path component of the first portion. We then have to
* copy the last part back on to get the final real path. Wheww.
*/
static int symlink_realpath(const char *name, char *resolved_path)
{
char *last_component;
char *tmp_path, *p;
size_t len = 0;
int rc = 0;
tmp_path = strdup(name);
if (!tmp_path) {
fprintf(stderr, "symlink_realpath(%s) strdup() failed: %s\n",
name, strerror(errno));
rc = -1;
goto out;
}
last_component = strrchr(tmp_path, '/');
if (last_component == tmp_path) {
last_component++;
p = strcpy(resolved_path, "/");
} else if (last_component) {
*last_component = '\0';
last_component++;
p = realpath(tmp_path, resolved_path);
} else {
last_component = tmp_path;
p = realpath("./", resolved_path);
}
if (!p) {
fprintf(stderr, "symlink_realpath(%s) realpath() failed: %s\n",
name, strerror(errno));
rc = -1;
goto out;
}
len = strlen(p);
if (len + strlen(last_component) + 1 > PATH_MAX) {
fprintf(stderr, "symlink_realpath(%s) failed: Filename too long \n",
name);
rc = -1;
goto out;
}
resolved_path += len;
strcpy(resolved_path, last_component);
out:
free(tmp_path);
return rc;
}
int matchpathcon(const char *path, mode_t mode, security_context_t * con)
{
char stackpath[PATH_MAX + 1];
char *p = NULL;
if (!hnd && (matchpathcon_init_prefix(NULL, NULL) < 0))
return -1;
if (S_ISLNK(mode)) {
if (!symlink_realpath(path, stackpath))
path = stackpath;
} else {
p = realpath(path, stackpath);
if (p)
path = p;
}
return notrans ?
selabel_lookup_raw(hnd, con, name, mode) :
selabel_lookup(hnd, con, name, mode);
selabel_lookup_raw(hnd, con, path, mode) :
selabel_lookup(hnd, con, path, mode);
}
int matchpathcon_index(const char *name, mode_t mode, security_context_t * con)

View File

@ -43,63 +43,6 @@ int printmatchpathcon(char *path, int header, int mode)
return 0;
}
/*
* We do not want to resolve a symlink to a real path if it is the final
* component of the name. Thus we split the pathname on the last "/" and
* determine a real path component of the first portion. We then have to
* copy the last part back on to get the final real path. Wheww.
*/
static int symlink_realpath(char *name, char *resolved_path)
{
char *last_component;
char *tmp_path, *p;
size_t len = 0;
int rc = 0;
tmp_path = strdup(name);
if (!tmp_path) {
fprintf(stderr, "symlink_realpath(%s) strdup() failed: %s\n",
name, strerror(errno));
rc = -1;
goto out;
}
last_component = strrchr(tmp_path, '/');
if (last_component == tmp_path) {
last_component++;
p = strcpy(resolved_path, "/");
} else if (last_component) {
*last_component = '\0';
last_component++;
p = realpath(tmp_path, resolved_path);
} else {
last_component = tmp_path;
p = realpath("./", resolved_path);
}
if (!p) {
fprintf(stderr, "symlink_realpath(%s) realpath() failed: %s\n",
name, strerror(errno));
rc = -1;
goto out;
}
len = strlen(p);
if (len + strlen(last_component) + 1 > PATH_MAX) {
fprintf(stderr, "symlink_realpath(%s) failed: Filename too long \n",
name);
rc = -1;
goto out;
}
resolved_path += len;
strcpy(resolved_path, last_component);
out:
free(tmp_path);
return rc;
}
int main(int argc, char **argv)
{
int i, init = 0;
@ -166,8 +109,7 @@ int main(int argc, char **argv)
for (i = optind; i < argc; i++) {
int rc, mode = 0;
struct stat buf;
char *p, *path = argv[i];
char stackpath[PATH_MAX + 1];
char *path = argv[i];
int len = strlen(path);
if (len > 1 && path[len - 1 ] == '/')
path[len - 1 ] = '\0';
@ -175,16 +117,6 @@ int main(int argc, char **argv)
if (lstat(path, &buf) == 0)
mode = buf.st_mode;
if (S_ISLNK(mode)) {
rc = symlink_realpath(path, stackpath);
if (!rc)
path = stackpath;
} else {
p = realpath(path, stackpath);
if (p)
path = p;
}
if (verify) {
rc = selinux_file_context_verify(path, mode);