Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
script-noexec: prevent anyscript which would call an external script
Baptiste Daroussin committed 1 year ago
commit 0c1fea2ba36604989b7ea2da5987de59fdbe24cb
parent fb1a060
10 files changed +58 -14
modified libpkg/pkg.h.in
@@ -414,7 +414,8 @@ typedef enum _pkg_flags {
	PKG_FLAG_FETCH_MIRROR = (1U << 10),
	PKG_FLAG_USE_IPV4 = (1U << 11),
	PKG_FLAG_USE_IPV6 = (1U << 12),
-
	PKG_FLAG_UPGRADE_VULNERABLE = (1U << 13)
+
	PKG_FLAG_UPGRADE_VULNERABLE = (1U << 13),
+
	PKG_FLAG_NOEXEC = (1U << 14)
} pkg_flags;

typedef enum _pkg_stats_t {
@@ -1050,6 +1051,7 @@ int pkg_add(struct pkgdb *db, const char *path, unsigned flags,
#define PKG_ADD_NOSCRIPT		(1U << 4)
#define PKG_ADD_FORCE_MISSING		(1U << 5)
#define PKG_ADD_SPLITTED_UPGRADE	(1U << 6)
+
#define PKG_ADD_NOEXEC			(1U << 7)

/**
 * Allocate a new pkg_jobs.
modified libpkg/pkg_add.c
@@ -1327,12 +1327,14 @@ pkg_add_cleanup_old(struct pkgdb *db, struct pkg *old, struct pkg *new, struct t
	 * Execute pre deinstall scripts
	 */
	if ((flags & PKG_ADD_NOSCRIPT) == 0) {
+
		bool noexec = ((flags & PKG_ADD_NOEXEC) == PKG_ADD_NOEXEC);
		ret = pkg_lua_script_run(old, PKG_LUA_PRE_DEINSTALL, (old != NULL));
		if (ret != EPKG_OK && ctx.developer_mode) {
			return (ret);
		} else {
-
			ret = pkg_script_run(old, PKG_SCRIPT_PRE_DEINSTALL, (old != NULL));
-
			if (ret != EPKG_OK && ctx.developer_mode) {
+
			ret = pkg_script_run(old, PKG_SCRIPT_PRE_DEINSTALL, (old != NULL),
+
			    noexec);
+
			if (ret != EPKG_OK && (ctx.developer_mode || noexec)) {
				return (ret);
			} else {
				ret = EPKG_OK;
@@ -1510,7 +1512,8 @@ pkg_add_common(struct pkg_add_db *db, const char *path, unsigned flags,
	if ((flags & PKG_ADD_NOSCRIPT) == 0) {
		if ((retcode = pkg_lua_script_run(pkg, PKG_LUA_PRE_INSTALL, (local != NULL))) != EPKG_OK)
			goto cleanup;
-
		if ((retcode = pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, (local != NULL))) != EPKG_OK)
+
		if ((retcode = pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, (local != NULL),
+
			    ((flags & PKG_ADD_NOEXEC) == PKG_ADD_NOEXEC))) != EPKG_OK)
			goto cleanup;
	}

@@ -1562,8 +1565,13 @@ pkg_add_common(struct pkg_add_db *db, const char *path, unsigned flags,
	if (retcode != EPKG_OK)
		goto cleanup;
	if ((flags & PKG_ADD_NOSCRIPT) == 0) {
+
		bool noexec = ((flags & PKG_ADD_NOEXEC) == PKG_ADD_NOEXEC);
		pkg_lua_script_run(pkg, PKG_LUA_POST_INSTALL, (local != NULL));
-
		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, (local != NULL));
+
		retcode = pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, (local != NULL),
+
		    noexec);
+
		if (retcode != EPKG_OK && noexec)
+
			goto cleanup;
+
		retcode = EPKG_OK;
	}

	/*
modified libpkg/pkg_delete.c
@@ -90,12 +90,13 @@ pkg_delete(struct pkg *pkg, struct pkg *rpkg, struct pkgdb *db, int flags,
		pkg_start_stop_rc_scripts(pkg, PKG_RC_STOP);

	if ((flags & (PKG_DELETE_NOSCRIPT | PKG_DELETE_UPGRADE)) == 0) {
+
		bool noexec = ((flags & PKG_DELETE_NOEXEC) == PKG_DELETE_NOEXEC);
		pkg_open_root_fd(pkg);
		ret = pkg_lua_script_run(pkg, PKG_LUA_PRE_DEINSTALL, false);
		if (ret != EPKG_OK && ctx.developer_mode)
			return (ret);
-
		ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL, false);
-
		if (ret != EPKG_OK && ctx.developer_mode)
+
		ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL, false, noexec);
+
		if (ret != EPKG_OK && (ctx.developer_mode || noexec))
			return (ret);
	}

@@ -106,8 +107,11 @@ pkg_delete(struct pkg *pkg, struct pkg *rpkg, struct pkgdb *db, int flags,
		return (ret);

	if ((flags & (PKG_DELETE_NOSCRIPT | PKG_DELETE_UPGRADE)) == 0) {
+
		bool noexec = ((flags & PKG_DELETE_NOEXEC) == PKG_DELETE_NOEXEC);
		pkg_lua_script_run(pkg, PKG_LUA_POST_DEINSTALL, false);
-
		pkg_script_run(pkg, PKG_SCRIPT_POST_DEINSTALL, false);
+
		ret = pkg_script_run(pkg, PKG_SCRIPT_POST_DEINSTALL, false, noexec);
+
		if (ret != EPKG_OK && (ctx.developer_mode || noexec))
+
			return (ret);
	}

	ret = pkg_delete_dirs(db, pkg, NULL);
modified libpkg/pkg_ports.c
@@ -1333,7 +1333,7 @@ pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
	if (!testing) {
		/* Execute pre-install scripts */
		pkg_lua_script_run(pkg, PKG_LUA_PRE_INSTALL, false);
-
		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, false);
+
		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, false, false);

		if (input_path != NULL) {
			pkg_register_cleanup_callback(pkg_rollback_cb, pkg);
@@ -1348,7 +1348,7 @@ pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,

		/* Execute post-install scripts */
		pkg_lua_script_run(pkg, PKG_LUA_POST_INSTALL, false);
-
		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, false);
+
		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, false, false);
	}

	if (rc == EPKG_OK) {
modified libpkg/private/pkg.h
@@ -626,6 +626,7 @@ int pkg_delete(struct pkg *pkg, struct pkg *rpkg, struct pkgdb *db, int flags,
    struct triggers *);
#define PKG_DELETE_UPGRADE	(1 << 1)	/* delete as a split upgrade */
#define PKG_DELETE_NOSCRIPT	(1 << 2)	/* don't run delete scripts */
+
#define PKG_DELETE_NOEXEC	(1 << 3)	/* don't run delete scripts which execute things*/

int pkg_fetch_file_to_fd(struct pkg_repo *repo, int dest, struct fetch_item *,
    bool silent);
@@ -660,7 +661,7 @@ int pkg_repo_load_fingerprints(struct pkg_repo *repo);

int pkg_start_stop_rc_scripts(struct pkg *, pkg_rc_attr attr);

-
int pkg_script_run(struct pkg *, pkg_script type, bool upgrade);
+
int pkg_script_run(struct pkg *, pkg_script type, bool upgrade, bool noexec);
int pkg_lua_script_run(struct pkg *, pkg_lua_script type, bool upgrade);
ucl_object_t *pkg_lua_script_to_ucl(stringlist_t *);
int pkg_script_run_child(int pid, int *pstat, int inputfd, const char* script_name);
modified libpkg/scripts.c
@@ -3,7 +3,7 @@
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
 * All rights reserved.
-
 * 
+
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
@@ -13,7 +13,7 @@
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
-
 * 
+
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@@ -51,7 +51,7 @@
extern char **environ;

int
-
pkg_script_run(struct pkg * const pkg, pkg_script type, bool upgrade)
+
pkg_script_run(struct pkg * const pkg, pkg_script type, bool upgrade, bool noexec)
{
	xstring *script_cmd = NULL;
	size_t i, j, script_len;
@@ -104,6 +104,11 @@ pkg_script_run(struct pkg * const pkg, pkg_script type, bool upgrade)
	for (j = 0; j < PKG_NUM_SCRIPTS; j++) {
		if (pkg_script_get(pkg, j) == NULL)
			continue;
+
		if (noexec) {
+
			pkg_emit_error("Attempt to execute a script, while forbidden");
+
			ret = EPKG_FATAL;
+
			break;
+
		}
		if (j == map[i].a || j == map[i].b) {
			xstring_renew(script_cmd);
			if (upgrade) {
modified src/add.c
@@ -70,12 +70,14 @@ exec_add(int argc, char **argv)
	int ch;
	int i;
	int failedpkgcount = 0;
+
	int scriptnoexec = 0;
	pkg_flags f = PKG_FLAG_NONE;
	const char *location = NULL;

	/* options descriptor */
	struct option longopts[] = {
		{ "no-scripts",          no_argument,            NULL,           'I' },
+
		{ "script-no-exec",      no_argument,            &scriptnoexec,  1 },
		{ "automatic",           no_argument,            NULL,           'A' },
		{ "force",               no_argument,            NULL,           'f' },
		{ "accept-missing",      no_argument,            NULL,           'M' },
@@ -105,6 +107,10 @@ exec_add(int argc, char **argv)
		case 1:
			location = optarg;
			break;
+
		case 0:
+
			if (scriptnoexec == 1)
+
				f |= PKG_ADD_NOEXEC;
+
			break;
		default:
			usage_add();
			return (EXIT_FAILURE);
modified src/delete.c
@@ -60,11 +60,13 @@ exec_delete(int argc, char **argv)
	int		 lock_type = PKGDB_LOCK_ADVISORY;
	int		 locked_pkgs = 0;
	int		 nbactions = 0;
+
	int		 scriptnoexec = 0;

	struct option longopts[] = {
		{ "all",			no_argument,	NULL,	'a' },
		{ "case-sensitive",		no_argument,	NULL,	'C' },
		{ "no-scripts",			no_argument,	NULL,	'D' },
+
		{ "script-no-exec",		no_argument,	&scriptnoexec,	1 },
		{ "force",			no_argument,	NULL,	'f' },
		{ "glob",			no_argument,	NULL,	'g' },
		{ "case-insensitive",		no_argument,	NULL,	'i' },
@@ -115,6 +117,10 @@ exec_delete(int argc, char **argv)
		case 'y':
			yes = true;
			break;
+
		case 0:
+
			if (scriptnoexec)
+
				f |= PKG_FLAG_NOEXEC;
+
			break;
		default:
			usage_delete();
			return (EXIT_FAILURE);
modified src/install.c
@@ -64,6 +64,7 @@ exec_install(int argc, char **argv)
	int		 done = 0;
	int		 lock_type = PKGDB_LOCK_ADVISORY;
	int		 nbactions = 0;
+
	int		 scriptnoexec = 0;
	bool		 rc = true;
	bool		 local_only = false;
	match_t		 match = MATCH_EXACT;
@@ -78,6 +79,7 @@ exec_install(int argc, char **argv)
		{ "glob",		no_argument,		NULL,	'g' },
		{ "case-insensitive",	no_argument,		NULL,	'i' },
		{ "no-scripts",		no_argument,		NULL,	'I' },
+
		{ "script-no-exec",	no_argument,		&scriptnoexec,	1 },
		{ "local-only",		no_argument,		NULL,	'l' },
		{ "ignore-missing",	no_argument,		NULL,	'M' },
		{ "dry-run",		no_argument,		NULL,	'n' },
@@ -152,6 +154,10 @@ exec_install(int argc, char **argv)
		case 'y':
			yes = true;
			break;
+
		case 0:
+
			if (scriptnoexec == 1)
+
				f |= PKG_FLAG_NOEXEC;
+
			break;
		default:
			usage_install();
			return (EXIT_FAILURE);
modified src/upgrade.c
@@ -247,6 +247,7 @@ exec_upgrade(int argc, char **argv)
	match_t		 match = MATCH_EXACT;
	int		 done = 0;
	int		 nbactions = 0;
+
	int		 scriptnoexec = 0;
	bool	rc = true;
	pkg_flags	 f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;
	c_charv_t	reponames;
@@ -258,6 +259,7 @@ exec_upgrade(int argc, char **argv)
		{ "glob",		no_argument,		NULL,	'g' },
		{ "case-insensitive",	no_argument,		NULL,	'i' },
		{ "no-scripts",		no_argument,		NULL,	'I' },
+
		{ "script-no-exec",	no_argument,		&scriptnoexec,	1 },
		{ "dry-run",		no_argument,		NULL,	'n' },
		{ "quiet",		no_argument,		NULL,	'q' },
		{ "repository",		required_argument,	NULL,	'r' },
@@ -314,6 +316,10 @@ exec_upgrade(int argc, char **argv)
		case 'v':
			f |= PKG_FLAG_UPGRADE_VULNERABLE;
			break;
+
		case 0:
+
			if (scriptnoexec == 1)
+
				f |= PKG_FLAG_NOEXEC;
+
			break;
		default:
			usage_upgrade();
			return (EXIT_FAILURE);