示例#1
0
int
copy_security_context(const char *from_file, const char *to_file)
{
	int status = 0;
#ifdef WITH_SELINUX
	security_context_t from_context;
	security_context_t to_context;

	if (selinux_enabled == -1)
		selinux_enabled = (is_selinux_enabled() > 0);

	if (!selinux_enabled)
		return 0;

	if (getfilecon(from_file, &from_context) < 0) {
		/*
		 * If the filesystem doesn't support extended
		 * attributes, the original had no special security
		 * context and the target cannot have one either.
		 */
		if (errno == EOPNOTSUPP)
			return 0;

		error(0, errno, joe_gettext(_("Could not get security context for %s")),
		      from_file);
		return 1;
	}

	if (getfilecon(to_file, &to_context) < 0) {
		MSG_PUTS(_(joe_gettext(_("\nCould not get security context for "))));
		msg_outtrans(to_file);
		msg_putchar('\n');
		freecon(from_context);
		return 1;
	}

	if (zcmp(from_context, to_context) != 0) {
		if (setfilecon(to_file, from_context) < 0) {
			error(0, errno,
			      joe_gettext(_("Could not set security context for %s")),
			      to_file);
			status = 1;
		}
	}

	freecon(to_context);
	freecon(from_context);
#endif
	return status;
}
  /*
   * Function: getFileCon
   * Purpose: retrieves the context associated with the given path in the file system
   * Parameters:
   *        path: given path in the file system
   * Returns:
   *        string representing the security context string of the file object
   *        the string may be NULL if an error occured
   * Exceptions: NullPointerException if the path object is null
   */
  static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) {
#ifdef HAVE_SELINUX
    if (isSELinuxDisabled)
      return NULL;

    if (path == NULL) {
      throw_NullPointerException(env, "Trying to check security context of a null path.");
      return NULL;
    }

    const char *objectPath = env->GetStringUTFChars(path, NULL);

    security_context_t context = NULL;
    jstring securityString = NULL;

    if (getfilecon(objectPath, &context) == -1)
      goto bail;

    ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath);

    securityString = env->NewStringUTF(context);

  bail:
    if (context != NULL)
      freecon(context);

    env->ReleaseStringUTFChars(path, objectPath);

    return securityString;
#else
    return NULL;
#endif
  }
static int
testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
{
    size_t i;
    security_context_t ctx;

    for (i = 0; i < nfiles; i++) {
        ctx = NULL;
        if (getfilecon(files[i].file, &ctx) < 0) {
            if (errno == ENODATA) {
                /* nothing to do */
            } else if (errno == EOPNOTSUPP) {
                if (VIR_STRDUP(ctx, "EOPNOTSUPP") < 0)
                    return -1;
            } else {
                virReportSystemError(errno,
                                     "Cannot read label on %s",
                                     files[i].file);
                return -1;
            }
        }
        if (STRNEQ_NULLABLE(files[i].context, ctx)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "File %s context '%s' did not match epected '%s'",
                           files[i].file, ctx, files[i].context);
            VIR_FREE(ctx);
            return -1;
        }
        VIR_FREE(ctx);
    }
    return 0;
}
示例#4
0
文件: runcon.c 项目: nawawi/busybox
static context_t runcon_compute_new_context(char *user, char *role, char *type, char *range,
			char *command, int compute_trans)
{
	context_t con;
	security_context_t cur_context;

	if (getcon(&cur_context))
		bb_error_msg_and_die("can't get current context");

	if (compute_trans) {
		security_context_t file_context, new_context;

		if (getfilecon(command, &file_context) < 0)
			bb_error_msg_and_die("can't retrieve attributes of '%s'",
					command);
		if (security_compute_create(cur_context, file_context,
					SECCLASS_PROCESS, &new_context))
			bb_error_msg_and_die("unable to compute a new context");
		cur_context = new_context;
	}

	con = context_new(cur_context);
	if (!con)
		bb_error_msg_and_die("'%s' is not a valid context", cur_context);
	if (user && context_user_set(con, user))
		bb_error_msg_and_die("can't set new user '%s'", user);
	if (type && context_type_set(con, type))
		bb_error_msg_and_die("can't set new type '%s'", type);
	if (range && context_range_set(con, range))
		bb_error_msg_and_die("can't set new range '%s'", range);
	if (role && context_role_set(con, role))
		bb_error_msg_and_die("can't set new role '%s'", role);

	return con;
}
示例#5
0
void 
setup_selinux_pty(const char *name, const char *tty)
{
  if (is_selinux_enabled() > 0) {
    security_context_t new_tty_context=NULL, user_context=NULL, old_tty_context=NULL;

    user_context=selinux_get_user_context(name);

    if (getfilecon(tty, &old_tty_context) < 0) {
      error("getfilecon(%.100s) failed: %.100s",
            tty, strerror(errno));
    } else {
      if (security_compute_relabel(user_context,old_tty_context,
                                   SECCLASS_CHR_FILE, &new_tty_context) != 0) {
        error("security_compute_relabel(%.100s) failed: "
              "%.100s", tty, strerror(errno));
      } else {
        if (setfilecon (tty, new_tty_context) != 0)
          error("setfilecon(%.100s, %s) failed: %.100s",
                tty, new_tty_context, strerror(errno));
        freecon(new_tty_context);
      }
      freecon(old_tty_context);
    }
    if (user_context) {
      freecon(user_context);
    }
  }
}
示例#6
0
static void
pw_unlock(void) {
	char tmp[FILENAMELEN+4];
  
	sprintf(tmp, "%s%s", orig_file, ".OLD");
	unlink(tmp);
	link(orig_file, tmp);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled()) {
	  security_context_t passwd_context=NULL;
	  int ret=0;
	  if (getfilecon(orig_file,&passwd_context) < 0) {
	    (void) fprintf(stderr,_("%s: Can't get context for %s"),progname,orig_file);
	    pw_error(orig_file, 1, 1);
	  }
	  ret=setfilecon(tmp_file,passwd_context);
	  freecon(passwd_context);
	  if (ret!=0) {
	    (void) fprintf(stderr,_("%s: Can't set context for %s"),progname,tmp_file);
	    pw_error(tmp_file, 1, 1);
	  }
	}
#endif

	if (rename(tmp_file, orig_file) == -1) {
		int errsv = errno;
		fprintf(stderr, 
			_("%s: can't unlock %s: %s (your changes are still in %s)\n"), 
			progname, orig_file, strerror(errsv), tmp_file);
		exit(1);
	}
	unlink(tmp_file);
}
示例#7
0
static int unmount_rename(const char *mtab, const char *mtab_new)
{
    int res;
    struct stat sbuf;

    if (stat(mtab, &sbuf) == 0)
        chown(mtab_new, sbuf.st_uid, sbuf.st_gid);

#ifdef HAVE_LIBSELINUX
    {
        security_context_t filecon;

        if (getfilecon(mtab, &filecon) > 0) {
            setfilecon(mtab_new, filecon);
            if (filecon != NULL)
                freecon(filecon);
        }
    }
#endif

    res = rename(mtab_new, mtab);
    if (res == -1) {
        fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
                mtab_new, mtab, strerror(errno));
        return -1;
    }
    return 0;
}
示例#8
0
static int
computecon (char const *path, mode_t mode, char **con)
{
  char *scon = NULL;
  char *tcon = NULL;
  security_class_t tclass;
  int rc = -1;

  char *dir = dir_name (path);
  if (!dir)
    goto quit;
  if (getcon (&scon) < 0)
    goto quit;
  if (getfilecon (dir, &tcon) < 0)
    goto quit;
  tclass = mode_to_security_class (mode);
  if (!tclass)
    goto quit;
  rc = security_compute_create (scon, tcon, tclass, con);

quit:
  free (dir);
  freecon (scon);
  freecon (tcon);
  return rc;
}
示例#9
0
int output_security_context(const char *from_file)
{
#ifdef WITH_SELINUX
	security_context_t scontext;

	if (selinux_enabled == -1)
		selinux_enabled = (is_selinux_enabled() > 0);
	if (!selinux_enabled)
		return 0;

	if (getfilecon(from_file, &scontext) < 0) {
		/*
		 * If the filesystem doesn't support extended
		 * attributes, the original had no special security
		 * context and the target cannot have one either.
		 */
		if (errno == EOPNOTSUPP)
			return 0;
		
		error(0, errno,joe_gettext(_("Could not get security context for %s")),
		      from_file);
		return 1;
	}

	error(0, 0, joe_gettext(_("%s Security Context %s")), from_file, scontext);
	freecon(scontext);
#endif
	return 0;
}
示例#10
0
文件: os_unix.c 项目: hoop33/neovim
// Copy security info from "from_file" to "to_file".
void mch_copy_sec(char_u *from_file, char_u *to_file)
{
  if (from_file == NULL)
    return;

  if (selinux_enabled == -1)
    selinux_enabled = is_selinux_enabled();

  if (selinux_enabled > 0) {
    security_context_t from_context = NULL;
    security_context_t to_context = NULL;

    if (getfilecon((char *)from_file, &from_context) < 0) {
      // If the filesystem doesn't support extended attributes,
      // the original had no special security context and the
      // target cannot have one either.
      if (errno == EOPNOTSUPP) {
        return;
      }

      MSG_PUTS(_("\nCould not get security context for "));
      msg_outtrans(from_file);
      msg_putchar('\n');
      return;
    }
    if (getfilecon((char *)to_file, &to_context) < 0) {
      MSG_PUTS(_("\nCould not get security context for "));
      msg_outtrans(to_file);
      msg_putchar('\n');
      freecon (from_context);
      return;
    }
    if (strcmp(from_context, to_context) != 0) {
      if (setfilecon((char *)to_file, from_context) < 0) {
        MSG_PUTS(_("\nCould not set security context for "));
        msg_outtrans(to_file);
        msg_putchar('\n');
      }
    }
    freecon(to_context);
    freecon(from_context);
  }
}
示例#11
0
static int set_context_from_socket( const struct service_config *scp, int fd )
{
   security_context_t curr_context = NULL;
   security_context_t peer_context = NULL;
   security_context_t exec_context = NULL;
   context_t bcon = NULL;
   context_t pcon = NULL;
   security_context_t new_context = NULL;
   security_context_t new_exec_context = NULL;
   int retval = -1;
   const char *exepath = NULL;

   if (getcon(&curr_context) < 0)
     goto fail;
   
   if (getpeercon(fd, &peer_context) < 0)
     goto fail;

   exepath = SC_SERVER_ARGV( scp )[0];
   if (getfilecon(exepath, &exec_context) < 0)
     goto fail;

   if (!(bcon = context_new(curr_context)))
     goto fail;

   if (!(pcon = context_new(peer_context)))
     goto fail;

   if (!context_range_get(pcon))
     goto fail;
   
   if (context_range_set(bcon, context_range_get(pcon)))
     goto fail;

   if (!(new_context = context_str(bcon)))
     goto fail;
   
   if (security_compute_create(new_context, exec_context, SECCLASS_PROCESS,
                               &new_exec_context) < 0)
     goto fail;

   retval = set_context(new_exec_context);

   freecon(new_exec_context);

 fail:
   context_free(pcon);
   context_free(bcon);
   freecon(exec_context);   
   freecon(peer_context);
   freecon(curr_context);

   return retval;
}
示例#12
0
static unsigned long chcon_parse_options(int argc, char *argv[])
{
	unsigned long opts;
	char *reference_file = NULL;

#ifdef CONFIG_FEATURE_CHCON_LONG_OPTIONS
	bb_applet_long_options = chcon_options;
#endif
	opts = bb_getopt_ulflags(argc, argv, "Rchf\n:u:r:t:l:v?\b",
				 &reference_file,
				 &user,
				 &role,
				 &type,
				 &range);

	if (opts & OPT_CHCON_VERSION) {
		printf("%s - busybox %s (build: %s)\n",
		       argv[0], BB_VER, BB_BT);
		exit(0);
	}

	if (opts & (OPT_CHCON_HELP | BB_GETOPT_ERROR))
		bb_show_usage();

	if ((opts & OPT_CHCON_QUIET) && (opts & OPT_CHCON_VERBOSE)) {
		fprintf(stderr, "could not specify quiet and verbose option same time\n");
		bb_show_usage();
	}

	if ((opts & OPT_CHCON_REFERENCE) && (opts & OPT_CHCON_COMPONENT_SPECIFIED)) {
		fprintf(stderr, "conflicting security context specifiers given\n");
		bb_show_usage();
	} else if (opts & OPT_CHCON_REFERENCE) {
		/* FIXME: lgetfilecon() should be used when '-h' is specified. */
		if (getfilecon(reference_file, &specified_context) < 0) {
			fprintf(stderr, "getfilecon('%s'), errno=%d (%s)\n",
				reference_file, errno, strerror(errno));
			exit(1);
		}
	} else if ((opts & OPT_CHCON_COMPONENT_SPECIFIED) == 0) {
		specified_context = argv[optind++];
		if (!specified_context) {
			fprintf(stderr, "too few arguments\n");
			bb_show_usage();
		}
	}
	target_files = argv + optind;
	if (!*target_files) {
		fprintf(stderr, "too few arguments\n");
		bb_show_usage();
	}
	return opts;
}
示例#13
0
/*  Set the context of all files associated with this VM to the new context
 *  complete with the unique generated category.
 */
static int
file_con_fixup (data_t *data)
{
        security_context_t sec_con = { 0, };
        context_t con = { 0, };
        char mcs_str[9] = { 0, };
        int ret = 0, p_ret = 0, i = 0;;
        
        p_ret = snprintf (mcs_str, sizeof (mcs_str), "s0:c%d", data->category);
        if (p_ret < 0 || p_ret > 9) {
                syslog (LOG_CRIT, "insufficient buffer size");
                return -1;
        }
        for (i = 0; data->files [i] != NULL; ++i) {
                if (getfilecon (data->files [i], &sec_con) == -1) {
                        syslog (LOG_CRIT,
                                "error getting context from file: %s, error %s",
                                data->files [i], strerror (errno));
                        continue;
                }
                con = context_new (sec_con);
                if (con == NULL) {
                        syslog (LOG_CRIT, 
                                "Error creating new context from string: %s",
                                sec_con);
                        ret = -1;
                        goto err_freecon;
                }
                if (context_range_set (con, mcs_str) == -1) {
                        syslog (LOG_CRIT, 
                                "Error setting context range to %s, "
                                "error: %s", mcs_str, strerror (errno));
                        ret = -1;
                        goto err_confree;
                }
                syslog (LOG_INFO, "Setting context for file %s to %s",
                        data->files [i], context_str (con));
                ret = setfilecon (data->files [i], context_str (con));
                if (ret != 0)
                        syslog (LOG_CRIT, "setfilecon error:%s",
                                strerror (errno));
                context_free (con);
                freecon (sec_con);
        }
        return ret;

 err_confree:
        context_free (con);
 err_freecon:
        freecon (sec_con);
        return ret;
}
示例#14
0
/* Attempt to change the label of PATH to TCON.  If OPTIONAL is true,
 * return 1 if labelling was not possible.  Otherwise, require a label
 * change, and return 0 for success, -1 for failure.  */
static int
SELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
{
    security_context_t econ;

    VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);

    if (setfilecon(path, tcon) < 0) {
        int setfilecon_errno = errno;

        if (getfilecon(path, &econ) >= 0) {
            if (STREQ(tcon, econ)) {
                freecon(econ);
                /* It's alright, there's nothing to change anyway. */
                return optional ? 1 : 0;
            }
            freecon(econ);
        }

        /* if the error complaint is related to an image hosted on
         * an nfs mount, or a usbfs/sysfs filesystem not supporting
         * labelling, then just ignore it & hope for the best.
         * The user hopefully set one of the necessary SELinux
         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
         */
        if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP) {
            virReportSystemError(setfilecon_errno,
                                 _("unable to set security context '%s' on '%s'"),
                                 tcon, path);
            if (security_getenforce() == 1)
                return -1;
        } else {
            const char *msg;
            if ((virStorageFileIsSharedFSType(path,
                                              VIR_STORAGE_FILE_SHFS_NFS) == 1) &&
                security_get_boolean_active("virt_use_nfs") != 1) {
                msg = _("Setting security context '%s' on '%s' not supported. "
                        "Consider setting virt_use_nfs");
               if (security_getenforce() == 1)
                   VIR_WARN(msg, tcon, path);
               else
                   VIR_INFO(msg, tcon, path);
            } else {
                VIR_INFO("Setting security context '%s' on '%s' not supported",
                         tcon, path);
            }
            if (optional)
                return 1;
        }
    }
    return 0;
}
示例#15
0
int chcon_main(int argc, char **argv)
{
	char *reference_file;
	char *fname;
	int i, errors = 0;

#if ENABLE_FEATURE_CHCON_LONG_OPTIONS
	applet_long_options = chcon_longopts;
#endif
	opt_complementary = "-1"  /* at least 1 param */
		":?"  /* error if exclusivity constraints are violated */
#if ENABLE_FEATURE_CHCON_LONG_OPTIONS
		":\xff--urtl:u--\xff:r--\xff:t--\xff:l--\xff"
#endif
		":f--v:v--f";  /* 'verbose' and 'quiet' are exclusive */
	getopt32(argv, "Rchfu:r:t:l:v",
		&user, &role, &type, &range, &reference_file);
	argv += optind;

#if ENABLE_FEATURE_CHCON_LONG_OPTIONS
	if (option_mask32 & OPT_REFERENCE) {
		/* FIXME: lgetfilecon() should be used when '-h' is specified.
		   But current implementation follows the original one. */
		if (getfilecon(reference_file, &specified_context) < 0)
			bb_perror_msg_and_die("getfilecon('%s') failed", reference_file);
	} else
#endif
	if ((option_mask32 & OPT_COMPONENT_SPECIFIED) == 0) {
		specified_context = *argv++;
		/* specified_context is never NULL -
		 * "-1" in opt_complementary prevents this. */
		if (!argv[0])
			bb_error_msg_and_die("too few arguments");
	}

	for (i = 0; (fname = argv[i]) != NULL; i++) {
		int fname_len = strlen(fname);
		while (fname_len > 1 && fname[fname_len - 1] == '/')
			fname_len--;
		fname[fname_len] = '\0';

		if (recursive_action(fname,
				     1<<option_mask32 & OPT_RECURSIVE,
				     change_filedir_context,
				     change_filedir_context,
				     NULL, 0) != TRUE)
			errors = 1;
	}
	return errors;
}
示例#16
0
static security_context_t
security_label_tty(pam_handle_t *pamh, char *tty,
		   security_context_t usercon)
{
  char ttybuf[PATH_MAX];
  int status=0;
  security_context_t newdev_context=NULL; /* The new context of a device */
  security_context_t prev_context=NULL; /* The new context of a device */
  const char *ptr;

  if(strncmp("/dev/", tty, 5))
  {
    snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty);
    ptr = ttybuf;
  }
  else
    ptr = tty;

  if (getfilecon(ptr, &prev_context) < 0)
  {
    if(errno != ENOENT)
      pam_syslog(pamh, LOG_NOTICE,
	     "Warning!  Could not get current context for %s, not relabeling: %m",
	     ptr);
    return NULL;
  }
  if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE,
                               &newdev_context)!=0)
  {
    pam_syslog(pamh, LOG_NOTICE,
           "Warning!  Could not get new context for %s, not relabeling: %m",
           ptr);
    pam_syslog(pamh, LOG_NOTICE,
	       "usercon=%s, prev_context=%s", usercon, prev_context);
    freecon(prev_context);
    return NULL;
  }
  status=setfilecon(ptr,newdev_context);
  if (status)
  {
      pam_syslog(pamh, LOG_NOTICE,
		 "Warning!  Could not relabel %s with %s, not relabeling: %m",
		 ptr,newdev_context);
      freecon(prev_context);
      prev_context=NULL;
  }
  freecon(newdev_context);
  return prev_context;
}
static void append_context_for_mount(char *mntpt, struct mkfs_opts *mop)
{
	security_context_t fcontext;

	if (getfilecon(mntpt, &fcontext) < 0) {
		/* Continuing with default behaviour */
		fprintf(stderr, "%s: Get file context failed : %s\n",
			progname, strerror(errno));
		return;
	}

	if (fcontext != NULL) {
		append_unique(mop->mo_ldd.ldd_mount_opts,
			      ",", "context", fcontext,
			      sizeof(mop->mo_ldd.ldd_mount_opts));
		freecon(fcontext);
	}
}
示例#18
0
/* Set the TTY context for the specified user */
void
ssh_selinux_setup_pty(char *pwname, const char *tty)
{
	security_context_t new_tty_ctx = NULL;
	security_context_t user_ctx = NULL;
	security_context_t old_tty_ctx = NULL;

	if (!ssh_selinux_enabled())
		return;

	debug3("%s: setting TTY context on %s", __func__, tty);

	user_ctx = ssh_selinux_getctxbyname(pwname);

	/* XXX: should these calls fatal() upon failure in enforcing mode? */

	if (getfilecon(tty, &old_tty_ctx) == -1) {
		error("%s: getfilecon: %s", __func__, strerror(errno));
		goto out;
	}

	if (security_compute_relabel(user_ctx, old_tty_ctx,
	    SECCLASS_CHR_FILE, &new_tty_ctx) != 0) {
		error("%s: security_compute_relabel: %s",
		    __func__, strerror(errno));
		goto out;
	}

	if (setfilecon(tty, new_tty_ctx) != 0)
		error("%s: setfilecon: %s", __func__, strerror(errno));
 out:
	if (new_tty_ctx != NULL)
		freecon(new_tty_ctx);
	if (old_tty_ctx != NULL)
		freecon(old_tty_ctx);
	if (user_ctx != NULL)
		freecon(user_ctx);
	debug3("%s: done", __func__);
}
示例#19
0
}

UINT32 aerofgt_state::aerofgt_ol2_tile_callback( UINT32 code )
{
	return m_spriteram2[code % (m_spriteram2.bytes()/2)];
}



/***************************************************************************

  Memory handlers

***************************************************************************/

WRITE16_MEMBER(aerofgt_state::aerofgt_bg1videoram_w)
{
	COMBINE_DATA(&m_bg1videoram[offset]);
	m_bg1_tilemap->mark_tile_dirty(offset);
}

WRITE16_MEMBER(aerofgt_state::aerofgt_bg2videoram_w)
{
	COMBINE_DATA(&m_bg2videoram[offset]);
	m_bg2_tilemap->mark_tile_dirty(offset);
}


void aerofgt_state::setbank( tilemap_t *tmap, int num, int bank )
{
	if (m_gfxbank[num] != bank)
	{
/*
 * Function: getFileCon
 * Purpose: retrieves the context associated with the given path in the file system
 * Parameters:
 *        path: given path in the file system
 * Returns:
 *        string representing the security context string of the file object
 *        the string may be NULL if an error occured
 * Exceptions: NullPointerException if the path object is null
 */
static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) {
    if (isSELinuxDisabled) {
        return NULL;
    }

    ScopedUtfChars path(env, pathStr);
    if (path.c_str() == NULL) {
        return NULL;
    }

    security_context_t tmp = NULL;
    int ret = getfilecon(path.c_str(), &tmp);
    Unique_SecurityContext context(tmp);

    ScopedLocalRef<jstring> securityString(env, NULL);
    if (ret != -1) {
        securityString.reset(env->NewStringUTF(context.get()));
    }

    ALOGV("getFileCon(%s) => %s", path.c_str(), context.get());
    return securityString.release();
}
示例#21
0
static void initselinux(char *username, char *full_tty,
                        security_context_t *user_sid)
{
    security_context_t old_tty_sid, new_tty_sid;

    if (!is_selinux_enabled())
        return;

    if (get_default_context(username, NULL, user_sid)) {
        bb_error_msg_and_die("can't get SID for %s", username);
    }
    if (getfilecon(full_tty, &old_tty_sid) < 0) {
        bb_perror_msg_and_die("getfilecon(%s) failed", full_tty);
    }
    if (security_compute_relabel(*user_sid, old_tty_sid,
                                 SECCLASS_CHR_FILE, &new_tty_sid) != 0) {
        bb_perror_msg_and_die("security_change_sid(%s) failed", full_tty);
    }
    if (setfilecon(full_tty, new_tty_sid) != 0) {
        bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid);
    }
}
示例#22
0
int label_get_socket_label_from_exe(const char *exe, char **label) {

        int r = 0;

#ifdef HAVE_SELINUX
        security_context_t mycon = NULL, fcon = NULL;
        security_class_t sclass;

        if (!use_selinux()) {
                *label = NULL;
                return 0;
        }

        r = getcon(&mycon);
        if (r < 0)
                goto fail;

        r = getfilecon(exe, &fcon);
        if (r < 0)
                goto fail;

        sclass = string_to_security_class("process");
        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
        if (r == 0)
                log_debug("SELinux Socket context for %s will be set to %s", exe, *label);

fail:
        if (r < 0 && security_getenforce() == 1)
                r = -errno;

        freecon(mycon);
        freecon(fcon);
#endif

        return r;
}
示例#23
0
文件: rpmsx.c 项目: avokhmin/RPM5
const char * rpmsxGetfilecon(rpmsx sx, const char *fn)
{
    const char * scon = NULL;

    if (sx == NULL) sx = rpmsxI();

if (_rpmsx_debug)
fprintf(stderr, "--> %s(%p,%s) sxfn %s\n", __FUNCTION__, sx, fn, sx->fn);

#if defined(WITH_SELINUX)
    if (sx->fn && fn) {
	security_context_t _con = NULL;
	int rc = getfilecon(fn, &_con);
	if (rc > 0 && _con != NULL)
	    scon = (const char *) _con;
	else
	    freecon(_con);
    }
#endif

if (_rpmsx_debug)
fprintf(stderr, "<-- %s(%p,%s) scon %s\n", __FUNCTION__, sx, fn, scon);
    return scon;
}
示例#24
0
文件: vipw.c 项目: hallyn/util-linux
static void pw_write(void)
{
	char tmp[FILENAMELEN + 4];

	sprintf(tmp, "%s%s", orig_file, ".OLD");
	unlink(tmp);

	if (link(orig_file, tmp))
		warn(_("%s: create a link to %s failed"), orig_file, tmp);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled() > 0) {
		security_context_t passwd_context = NULL;
		int ret = 0;
		if (getfilecon(orig_file, &passwd_context) < 0) {
			warnx(_("Can't get context for %s"), orig_file);
			pw_error(orig_file, 1, 1);
		}
		ret = setfilecon(tmp_file, passwd_context);
		freecon(passwd_context);
		if (ret != 0) {
			warnx(_("Can't set context for %s"), tmp_file);
			pw_error(tmp_file, 1, 1);
		}
	}
#endif

	if (rename(tmp_file, orig_file) == -1) {
		int errsv = errno;
		errx(EXIT_FAILURE,
		     ("cannot write %s: %s (your changes are still in %s)"),
		     orig_file, strerror(errsv), tmp_file);
	}
	unlink(tmp_file);
	free(tmp_file);
}
示例#25
0
static int change_file_context(const char *file, unsigned long opts)
{
	security_context_t file_context = NULL;
	security_context_t context_string;
	context_t context;
	int errors = 0;
	int status = 0;

	if (opts & OPT_CHCON_NODEREFERENCE) {
		status = lgetfilecon(file, &file_context);
	} else {
		status = getfilecon(file, &file_context);
	}
	if (status < 0 && errno != ENODATA) {
		if ((opts & OPT_CHCON_QUIET) == 0)
			fprintf(stderr, "could not obtain security context: %s\n", file);
		return 1;
	}

	if (file_context == NULL && specified_context == NULL) {
		fprintf(stderr, "can't apply partial context to unlabeled file %s", file);
		return 1;
	}

	if (specified_context == NULL) {
		context = compute_context_from_mask(file_context, opts);
		if (!context) {
			fprintf(stderr, "couldn't compute security context from %s",
				file_context);
			return 1;
		}
	} else {
		context = context_new(specified_context);
		if (!context) {
			fprintf(stderr, "invalid context: %s", specified_context);
			return 1;
		}
	}

	context_string = context_str(context);
	if (file_context == NULL || strcmp(context_string, file_context)!=0) {
		int fail = 0;

		if (opts & OPT_CHCON_NODEREFERENCE) {
			fail = lsetfilecon (file, context_string);
		} else {
			fail = setfilecon (file, context_string);
		}
		if ((opts & OPT_CHCON_VERBOSE)
		    || ((opts & OPT_CHCON_CHANHES) && !fail)) {
			printf(!fail
			       ? "context of %s changed to %s\n"
			       : "failed to change context of %s to %s\n",
			       file, context_string);
		}
		if (fail) {
			errors = 1;
			if ((opts & OPT_CHCON_QUIET) == 0)
				fprintf(stderr, "failed to change context of %s to %s\n",
					file, context_string);
		}
	} else if (opts & OPT_CHCON_VERBOSE) {
		printf("context of %s retained as %s\n", file, context_string);
	}
	context_free(context);
	freecon(file_context);

	if (opts & OPT_CHCON_RECURSIVE) {
		struct stat file_stats;
		if (lstat(file, &file_stats) == 0
		    && S_ISDIR(file_stats.st_mode))
			errors |= change_dir_context(file, opts);
	}
	return errors;
}
示例#26
0
/*
   This function communicates with the kernel to check whether or not it should
   allow the access.
   If the machine is in permissive mode it will return ok.  Audit messages will
   still be generated if the access would be denied in enforcing mode.
*/
int selinux_access_check(
                DBusConnection *connection,
                DBusMessage *message,
                const char *path,
                const char *permission,
                DBusError *error) {

        security_context_t scon = NULL, fcon = NULL;
        int r = 0;
        const char *tclass = NULL;
        struct auditstruct audit;

        assert(connection);
        assert(message);
        assert(permission);
        assert(error);

        if (!use_selinux())
                return 0;

        r = selinux_access_init(error);
        if (r < 0)
                return r;

        log_debug("SELinux access check for path=%s permission=%s", strna(path), permission);

        audit.uid = audit.loginuid = (uid_t) -1;
        audit.gid = (gid_t) -1;
        audit.cmdline = NULL;
        audit.path = path;

        r = get_calling_context(connection, message, &scon, error);
        if (r < 0) {
                log_error("Failed to get caller's security context on: %m");
                goto finish;
        }

        if (path) {
                tclass = "service";
                /* get the file context of the unit file */
                r = getfilecon(path, &fcon);
                if (r < 0) {
                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
                        r = -errno;
                        log_error("Failed to get security context on %s: %m",path);
                        goto finish;
                }

        } else {
                tclass = "system";
                r = getcon(&fcon);
                if (r < 0) {
                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                        r = -errno;
                        log_error("Failed to get current process context on: %m");
                        goto finish;
                }
        }

        (void) get_audit_data(connection, message, &audit, error);

        errno = 0;
        r = selinux_check_access(scon, fcon, tclass, permission, &audit);
        if (r < 0) {
                dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
                r = -errno;
                log_error("SELinux policy denies access.");
        }

        log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);

finish:
        free(audit.cmdline);
        freecon(scon);
        freecon(fcon);

        if (r && security_getenforce() != 1) {
                dbus_error_init(error);
                r = 0;
        }

        return r;
}
void service_start(struct service *svc, const char *dynamic_args)
{
    struct stat s;
    pid_t pid;
    int needs_console;
    int n;
#ifdef HAVE_SELINUX
    char *scon = NULL;
    int rc;
#endif
        /* starting a service removes it from the disabled or reset
         * state and immediately takes it out of the restarting
         * state if it was in there
         */
    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET));
    svc->time_started = 0;

        /* running processes require no additional work -- if
         * they're in the process of exiting, we've ensured
         * that they will immediately restart on exit, unless
         * they are ONESHOT
         */
    if (svc->flags & SVC_RUNNING) {
        return;
    }

    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
    if (needs_console && (!have_console)) {
        ERROR("service '%s' requires console\n", svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }

    if (stat(svc->args[0], &s) != 0) {
        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }

    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
               svc->args[0]);
        svc->flags |= SVC_DISABLED;
        return;
    }

#ifdef HAVE_SELINUX
    if (is_selinux_enabled() > 0) {
        char *mycon = NULL, *fcon = NULL;

        INFO("computing context for service '%s'\n", svc->args[0]);
        rc = getcon(&mycon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", svc->name);
            return;
        }

        rc = getfilecon(svc->args[0], &fcon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", svc->name);
            freecon(mycon);
            return;
        }

        rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
        freecon(mycon);
        freecon(fcon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", svc->name);
            return;
        }
    }
#endif

    NOTICE("starting '%s'\n", svc->name);

    pid = fork();

    if (pid == 0) {
        struct socketinfo *si;
        struct svcenvinfo *ei;
        char tmp[32];
        int fd, sz;

        umask(077);
#ifdef __arm__
        /*
         * b/7188322 - Temporarily revert to the compat memory layout
         * to avoid breaking third party apps.
         *
         * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
         *
         * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
         * changes the kernel mapping from bottom up to top-down.
         * This breaks some programs which improperly embed
         * an out of date copy of Android's linker.
         */
        int current = personality(0xffffFFFF);
        personality(current | ADDR_COMPAT_LAYOUT);
#endif
        if (properties_inited()) {
            get_property_workspace(&fd, &sz);
            sprintf(tmp, "%d,%d", dup(fd), sz);
            add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
        }

        for (ei = svc->envvars; ei; ei = ei->next)
            add_environment(ei->name, ei->value);

#ifdef HAVE_SELINUX
        setsockcreatecon(scon);
#endif

        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);
            if (s >= 0) {
                publish_socket(si->name, s);
            }
        }

#ifdef HAVE_SELINUX
        freecon(scon);
        scon = NULL;
        setsockcreatecon(NULL);
#endif

        if (svc->ioprio_class != IoSchedClass_NONE) {
            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
            }
        }

        if (needs_console) {
            setsid();
            open_console();
        } else {
            zap_stdio();
        }

#if 0
        for (n = 0; svc->args[n]; n++) {
            INFO("args[%d] = '%s'\n", n, svc->args[n]);
        }
        for (n = 0; ENV[n]; n++) {
            INFO("env[%d] = '%s'\n", n, ENV[n]);
        }
#endif

        setpgid(0, getpid());

    /* as requested, set our gid, supplemental gids, and uid */
        if (svc->gid) {
            if (setgid(svc->gid) != 0) {
                ERROR("setgid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->nr_supp_gids) {
            if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) {
                ERROR("setgroups failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->uid) {
            if (setuid(svc->uid) != 0) {
                ERROR("setuid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }

#ifdef HAVE_SELINUX
        if (svc->seclabel) {
            if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
                ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
                _exit(127);
            }
        }
#endif

        if (!dynamic_args) {
            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
            }
        } else {
            char *arg_ptrs[INIT_PARSER_MAXARGS+1];
            int arg_idx = svc->nargs;
            char *tmp = strdup(dynamic_args);
            char *next = tmp;
            char *bword;

            /* Copy the static arguments */
            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));

            while((bword = strsep(&next, " "))) {
                arg_ptrs[arg_idx++] = bword;
                if (arg_idx == INIT_PARSER_MAXARGS)
                    break;
            }
            arg_ptrs[arg_idx] = '\0';
            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
        }
        _exit(127);
    }

#ifdef HAVE_SELINUX
    freecon(scon);
#endif

    if (pid < 0) {
        ERROR("failed to start '%s'\n", svc->name);
        svc->pid = 0;
        return;
    }

    svc->time_started = gettime();
    svc->pid = pid;
    svc->flags |= SVC_RUNNING;

    if (properties_inited())
        notify_service_state(svc->name, "running");
}
示例#28
0
int
rpl_getfilecon (char const *file, security_context_t *con)
{
  int ret = getfilecon (file, con);
  return map_to_failure (ret, con);
}
示例#29
0
/*
   This function communicates with the kernel to check whether or not it should
   allow the access.
   If the machine is in permissive mode it will return ok.  Audit messages will
   still be generated if the access would be denied in enforcing mode.
*/
int mac_selinux_generic_access_check(
                sd_bus_message *message,
                const char *path,
                const char *permission,
                sd_bus_error *error) {

#ifdef HAVE_SELINUX
        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        const char *tclass = NULL, *scon = NULL;
        struct audit_info audit_info = {};
        _cleanup_free_ char *cl = NULL;
        security_context_t fcon = NULL;
        char **cmdline = NULL;
        int r = 0;

        assert(message);
        assert(permission);
        assert(error);

        if (!mac_selinux_use())
                return 0;

        r = mac_selinux_access_init(error);
        if (r < 0)
                return r;

        r = sd_bus_query_sender_creds(
                        message,
                        SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|
                        SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID|
                        SD_BUS_CREDS_SELINUX_CONTEXT|
                        SD_BUS_CREDS_AUGMENT /* get more bits from /proc */,
                        &creds);
        if (r < 0)
                goto finish;

        /* The SELinux context is something we really should have
         * gotten directly from the message or sender, and not be an
         * augmented field. If it was augmented we cannot use it for
         * authorization, since this is racy and vulnerable. Let's add
         * an extra check, just in case, even though this really
         * shouldn't be possible. */
        assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_SELINUX_CONTEXT) == 0, -EPERM);

        r = sd_bus_creds_get_selinux_context(creds, &scon);
        if (r < 0)
                goto finish;

        if (path) {
                /* Get the file context of the unit file */

                r = getfilecon(path, &fcon);
                if (r < 0) {
                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
                        goto finish;
                }

                tclass = "service";
        } else {
                r = getcon(&fcon);
                if (r < 0) {
                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                        goto finish;
                }

                tclass = "system";
        }

        sd_bus_creds_get_cmdline(creds, &cmdline);
        cl = strv_join(cmdline, " ");

        audit_info.creds = creds;
        audit_info.path = path;
        audit_info.cmdline = cl;

        r = selinux_check_access(scon, fcon, tclass, permission, &audit_info);
        if (r < 0)
                r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");

        log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r);

finish:
        freecon(fcon);

        if (r < 0 && security_getenforce() != 1) {
                sd_bus_error_free(error);
                r = 0;
        }

        return r;
#else
        return 0;
#endif
}
示例#30
0
int main(int argc, char **argv)
{
	/* these vars are reused several times */
	int rc, opt, i, c;
	char *context, *root_path;

	/* files that need context checks */
	char *fc[MAX_CHECK];
	char *cterm = ttyname(0);
	int nfc = 0;
	struct stat m;

	/* processes that need context checks */
	char *pc[MAX_CHECK];
	int npc = 0;

	/* booleans */
	char **bools;
	int nbool;

	int verbose = 0;
	int show_bools = 0;

	/* policy */
	const char *pol_name, *root_dir;
	char *pol_path;


	while (1) {
		opt = getopt(argc, argv, "vb");
		if (opt == -1)
			break;
		switch (opt) {
		case 'v':
			verbose = 1;
			break;
		case 'b':
			show_bools = 1;
			break;
		default:
			/* invalid option */
			printf("\nUsage: %s [OPTION]\n\n", basename(argv[0]));
			printf("  -v  Verbose check of process and file contexts.\n");
			printf("  -b  Display current state of booleans.\n");
			printf("\nWithout options, show SELinux status.\n");
			return -1;
		}
	}
	printf_tab("SELinux status:");
	rc = is_selinux_enabled();

	switch (rc) {
	case 1:
		printf("enabled\n");
		break;
	case 0:
		printf("disabled\n");
		return 0;
		break;
	default:
		printf("unknown (%s)\n", strerror(errno));
		return 0;
		break;
	}

	printf_tab("SELinuxfs mount:");
	if (selinux_mnt != NULL) {
		printf("%s\n", selinux_mnt);
	} else {
		printf("not mounted\n\n");
		printf("Please mount selinuxfs for proper results.\n");
		return -1;
	}

	printf_tab("SELinux root directory:");
	root_dir = selinux_path();
	if (root_dir == NULL) {
		printf("error (%s)\n", strerror(errno));
		return -1;
	}
	/* The path has a trailing '/' so duplicate to edit */
	root_path = strdup(root_dir);
	if (!root_path) {
		printf("malloc error (%s)\n", strerror(errno));
		return -1;
	}
	/* actually blank the '/' */
	root_path[strlen(root_path) - 1] = '\0';
	printf("%s\n", root_path);
	free(root_path);

	/* Dump all the path information */
	printf_tab("Loaded policy name:");
	pol_path = strdup(selinux_policy_root());
	if (pol_path) {
		pol_name = basename(pol_path);
		puts(pol_name);
		free(pol_path);
	} else {
		printf("error (%s)\n", strerror(errno));
	}

	printf_tab("Current mode:");
	rc = security_getenforce();
	switch (rc) {
	case 1:
		printf("enforcing\n");
		break;
	case 0:
		printf("permissive\n");
		break;
	default:
		printf("unknown (%s)\n", strerror(errno));
		break;
	}

	printf_tab("Mode from config file:");
	if (selinux_getenforcemode(&rc) == 0) {
		switch (rc) {
		case 1:
			printf("enforcing\n");
			break;
		case 0:
			printf("permissive\n");
			break;
		case -1:
			printf("disabled\n");
			break;
		}
	} else {
		printf("error (%s)\n", strerror(errno));
	}

	printf_tab("Policy MLS status:");
	rc = is_selinux_mls_enabled();
	switch (rc) {
		case 0:
			printf("disabled\n");
			break;
		case 1:
			printf("enabled\n");
			break;
		default:
			printf("error (%s)\n", strerror(errno));
			break;
	}

	printf_tab("Policy deny_unknown status:");
	rc = security_deny_unknown();
	switch (rc) {
		case 0:
			printf("allowed\n");
			break;
		case 1:
			printf("denied\n");
			break;
		default:
			printf("error (%s)\n", strerror(errno));
			break;
	}

	rc = security_policyvers();
	printf_tab("Max kernel policy version:");
	if (rc < 0)
		printf("unknown (%s)\n", strerror(errno));
	else
		printf("%d\n", rc);


	if (show_bools) {
		/* show booleans */
		if (security_get_boolean_names(&bools, &nbool) >= 0) {
			printf("\nPolicy booleans:\n");

			for (i = 0; i < nbool; i++) {
				if (strlen(bools[i]) + 1 > COL)
					COL = strlen(bools[i]) + 1;
			}
			for (i = 0; i < nbool; i++) {
				printf_tab(bools[i]);

				rc = security_get_boolean_active(bools[i]);
				switch (rc) {
				case 1:
					printf("on");
					break;
				case 0:
					printf("off");
					break;
				default:
					printf("unknown (%s)", strerror(errno));
					break;
				}
				c = security_get_boolean_pending(bools[i]);
				if (c != rc)
					switch (c) {
					case 1:
						printf(" (activate pending)");
						break;
					case 0:
						printf(" (inactivate pending)");
						break;
					default:
						printf(" (pending error: %s)",
						       strerror(errno));
						break;
					}
				printf("\n");

				/* free up the booleans */
				free(bools[i]);
			}
			free(bools);
		}
	}
	/* only show contexts if -v is given */
	if (!verbose)
		return 0;

	load_checks(pc, &npc, fc, &nfc);

	printf("\nProcess contexts:\n");

	printf_tab("Current context:");
	if (getcon(&context) >= 0) {
		printf("%s\n", context);
		freecon(context);
	} else
		printf("unknown (%s)\n", strerror(errno));

	printf_tab("Init context:");
	if (getpidcon(1, &context) >= 0) {
		printf("%s\n", context);
		freecon(context);
	} else
		printf("unknown (%s)\n", strerror(errno));

	for (i = 0; i < npc; i++) {
		rc = pidof(pc[i]);
		if (rc > 0) {
			if (getpidcon(rc, &context) < 0)
				continue;

			printf_tab(pc[i]);
			printf("%s\n", context);
			freecon(context);
		}
	}

	printf("\nFile contexts:\n");

	/* controlling term */
	printf_tab("Controlling terminal:");
	if (lgetfilecon(cterm, &context) >= 0) {
		printf("%s\n", context);
		freecon(context);
	} else {
		printf("unknown (%s)\n", strerror(errno));
	}

	for (i = 0; i < nfc; i++) {
		if (lgetfilecon(fc[i], &context) >= 0) {
			printf_tab(fc[i]);

			/* check if this is a symlink */
			if (lstat(fc[i], &m)) {
				printf
				    ("%s (could not check link status (%s)!)\n",
				     context, strerror(errno));
				freecon(context);
				continue;
			}
			if (S_ISLNK(m.st_mode)) {
				/* print link target context */
				printf("%s -> ", context);
				freecon(context);

				if (getfilecon(fc[i], &context) >= 0) {
					printf("%s\n", context);
					freecon(context);
				} else {
					printf("unknown (%s)\n",
					       strerror(errno));
				}
			} else {
				printf("%s\n", context);
				freecon(context);
			}
		}
	}

	return 0;
}