Linux Test Project
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@linux.ibm.com>
To: Alex Henrie <alexh@vpitech.com>,
	linux-integrity@vger.kernel.org, ltp@lists.linux.it,
	pvorel@suse.cz, alexhenrie24@gmail.com
Cc: Curtis Veit <veit@vpieng.com>
Subject: Re: [LTP] [PATCH linux rebase] ima: add gid support
Date: Mon, 04 Oct 2021 18:30:55 -0400	[thread overview]
Message-ID: <e6d38bb046c85ecf1eb76ba45b989fd6853c416a.camel@linux.ibm.com> (raw)
In-Reply-To: <20210909165111.51038-1-alexh@vpitech.com>

On Thu, 2021-09-09 at 10:51 -0600, Alex Henrie wrote:
> From: Curtis Veit <veit@vpieng.com>
> 
> IMA currently supports the concept of rules based on uid where the rule
> is based on the uid of the file owner or the uid of the user accessing
> the file. It is useful to have similar rules based on gid. This patch
> provides that ability.
> 
> Signed-off-by: Curtis Veit <veit@vpieng.com>
> Co-developed-by: Alex Henrie <alexh@vpitech.com>
> Signed-off-by: Alex Henrie <alexh@vpitech.com>

Thanks, Alex.  There are a couple of places were the code is
duplicated, except for the indentation.   At least for now, let's keep
the line length at 80 chars.  Similarly, when extending a
comment/documentation, please split the line.

A few minor comments below, otherwise:

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

> ---
> This is the patch that Curtis sent in 2015,[1] rebased and with support
> for effective GID and the new greater-than and less-than operators.
> Moreover, the policy_opt enum is now in the same order as the
> policy_tokens array, which I'm guessing is the bug that prevented the
> patch from being accepted before.

That sounds right.

> 
> [1] https://sourceforge.net/p/linux-ima/mailman/message/34210250/
> ---
>  Documentation/ABI/testing/ima_policy |   5 +-
>  security/integrity/ima/ima_policy.c  | 197 +++++++++++++++++++++++----
>  2 files changed, 174 insertions(+), 28 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> index 5c2798534950..f8e5b5598548 100644
> --- a/Documentation/ABI/testing/ima_policy
> +++ b/Documentation/ABI/testing/ima_policy
> @@ -23,7 +23,7 @@ Description:
>  			  audit | hash | dont_hash
>  		  condition:= base | lsm  [option]
>  			base:	[[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
> -				[euid=] [fowner=] [fsname=]]
> +				[euid=] [gid=] [egid=] [fowner=] [fgroup=] [fsname=]]

Like in other places where you modified the ordering, let's group uid,
euid, git, egid, etc together on the same line.

>  			lsm:	[[subj_user=] [subj_role=] [subj_type=]
>  				 [obj_user=] [obj_role=] [obj_type=]]
>  			option:	[[appraise_type=]] [template=] [permit_directio]
> @@ -40,7 +40,10 @@ Description:
>  			fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
>  			uid:= decimal value
>  			euid:= decimal value
> +			gid:= decimal value
> +			egid:= decimal value
>  			fowner:= decimal value
> +			fgroup:= decimal value
>  		  lsm:  are LSM specific
>  		  option:
>  			appraise_type:= [imasig] [imasig|modsig]
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 87b9b71cb820..0f2287699f85 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -36,6 +36,9 @@
>  #define IMA_KEYRINGS	0x0400
>  #define IMA_LABEL	0x0800
>  #define IMA_VALIDATE_ALGOS	0x1000
> +#define IMA_GID		0x2000
> +#define IMA_EGID	0x4000
> +#define IMA_FGROUP	0x8000

Ok, any additional changes after this will need to increase the "flags"
size.

>  
>  #define UNKNOWN		0
>  #define MEASURE		0x0001	/* same as IMA_MEASURE */
> @@ -78,9 +81,13 @@ struct ima_rule_entry {
>  	unsigned long fsmagic;
>  	uuid_t fsuuid;
>  	kuid_t uid;
> +	kgid_t gid;
>  	kuid_t fowner;
> +	kgid_t fgroup;
>  	bool (*uid_op)(kuid_t, kuid_t);    /* Handlers for operators       */
> +	bool (*gid_op)(kgid_t, kgid_t);
>  	bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
> +	bool (*fgroup_op)(kgid_t, kgid_t); /* gid_eq(), gid_gt(), gid_lt() */
>  	int pcr;
>  	unsigned int allowed_algos; /* bitfield of allowed hash algorithms */
>  	struct {
> @@ -104,7 +111,8 @@ static_assert(
>  
>  /*
>   * Without LSM specific knowledge, the default policy can only be
> - * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
> + * written in terms of .action, .func, .mask, .fsmagic, .uid, .gid,
> + * .fowner, and .fgroup
>   */
>  
>  /*
> @@ -582,10 +590,23 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
>  		} else if (!rule->uid_op(cred->euid, rule->uid))
>  			return false;
>  	}
> -
> +	if ((rule->flags & IMA_GID) && !rule->gid_op(rule->gid, cred->gid))
> +		return false;
> +	if (rule->flags & IMA_EGID) {
> +		if (has_capability_noaudit(current, CAP_SETGID)) {
> +			if (!rule->gid_op(cred->egid, rule->gid)
> +			    && !rule->gid_op(cred->sgid, rule->gid)
> +			    && !rule->gid_op(cred->gid, rule->gid))
> +				return false;
> +		} else if (!rule->gid_op(cred->egid, rule->gid))
> +			return false;
> +	}
>  	if ((rule->flags & IMA_FOWNER) &&
>  	    !rule->fowner_op(i_uid_into_mnt(mnt_userns, inode), rule->fowner))
>  		return false;
> +	if ((rule->flags & IMA_FGROUP) &&
> +	    !rule->fgroup_op(i_gid_into_mnt(mnt_userns, inode), rule->fgroup))
> +		return false;
>  	for (i = 0; i < MAX_LSM_RULES; i++) {
>  		int rc = 0;
>  		u32 osid;
> @@ -987,16 +1008,19 @@ void ima_update_policy(void)
>  }
>  
>  /* Keep the enumeration in sync with the policy_tokens! */
> -enum {
> +enum policy_opt {
>  	Opt_measure, Opt_dont_measure,
>  	Opt_appraise, Opt_dont_appraise,
>  	Opt_audit, Opt_hash, Opt_dont_hash,
>  	Opt_obj_user, Opt_obj_role, Opt_obj_type,
>  	Opt_subj_user, Opt_subj_role, Opt_subj_type,
> -	Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname,
> -	Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
> -	Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
> -	Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
> +	Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, Opt_fsuuid,
> +	Opt_uid_eq, Opt_euid_eq, Opt_gid_eq, Opt_egid_eq,
> +	Opt_fowner_eq, Opt_fgroup_eq,
> +	Opt_uid_gt, Opt_euid_gt, Opt_gid_gt, Opt_egid_gt,
> +	Opt_fowner_gt, Opt_fgroup_gt,
> +	Opt_uid_lt, Opt_euid_lt, Opt_gid_lt, Opt_egid_lt,
> +	Opt_fowner_lt, Opt_fgroup_lt,
>  	Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos,
>  	Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
>  	Opt_label, Opt_err
> @@ -1023,13 +1047,22 @@ static const match_table_t policy_tokens = {
>  	{Opt_fsuuid, "fsuuid=%s"},
>  	{Opt_uid_eq, "uid=%s"},
>  	{Opt_euid_eq, "euid=%s"},
> +	{Opt_gid_eq, "gid=%s"},
> +	{Opt_egid_eq, "egid=%s"},
>  	{Opt_fowner_eq, "fowner=%s"},
> +	{Opt_fgroup_eq, "fgroup=%s"},
>  	{Opt_uid_gt, "uid>%s"},
>  	{Opt_euid_gt, "euid>%s"},
> +	{Opt_gid_gt, "gid>%s"},
> +	{Opt_egid_gt, "egid>%s"},
>  	{Opt_fowner_gt, "fowner>%s"},
> +	{Opt_fgroup_gt, "fgroup>%s"},
>  	{Opt_uid_lt, "uid<%s"},
>  	{Opt_euid_lt, "euid<%s"},
> +	{Opt_gid_lt, "gid<%s"},
> +	{Opt_egid_lt, "egid<%s"},
>  	{Opt_fowner_lt, "fowner<%s"},
> +	{Opt_fgroup_lt, "fgroup<%s"},
>  	{Opt_appraise_type, "appraise_type=%s"},
>  	{Opt_appraise_flag, "appraise_flag=%s"},
>  	{Opt_appraise_algos, "appraise_algos=%s"},
> @@ -1073,22 +1106,36 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
>  }
>  
>  static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
> -			      bool (*rule_operator)(kuid_t, kuid_t))
> +			      enum policy_opt rule_operator)
>  {
>  	if (!ab)
>  		return;
>  
> -	if (rule_operator == &uid_gt)
> +	switch (rule_operator) {
> +	case Opt_uid_gt:
> +	case Opt_euid_gt:
> +	case Opt_gid_gt:
> +	case Opt_egid_gt:
> +	case Opt_fowner_gt:
> +	case Opt_fgroup_gt:
>  		audit_log_format(ab, "%s>", key);
> -	else if (rule_operator == &uid_lt)
> +		break;
> +	case Opt_uid_lt:
> +	case Opt_euid_lt:
> +	case Opt_gid_lt:
> +	case Opt_egid_lt:
> +	case Opt_fowner_lt:
> +	case Opt_fgroup_lt:
>  		audit_log_format(ab, "%s<", key);
> -	else
> +		break;
> +	default:
>  		audit_log_format(ab, "%s=", key);
> +	}
>  	audit_log_format(ab, "%s ", value);
>  }
>  static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
>  {
> -	ima_log_string_op(ab, key, value, NULL);
> +	ima_log_string_op(ab, key, value, Opt_err);
>  }
>  
>  /*
> @@ -1163,7 +1210,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  		if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
>  				     IMA_UID | IMA_FOWNER | IMA_FSUUID |
>  				     IMA_INMASK | IMA_EUID | IMA_PCR |
> -				     IMA_FSNAME | IMA_DIGSIG_REQUIRED |
> +				     IMA_FSNAME | IMA_GID | IMA_EGID |
> +				     IMA_FGROUP | IMA_DIGSIG_REQUIRED |
>  				     IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS))
>  			return false;
>  
> @@ -1174,7 +1222,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  		if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
>  				     IMA_UID | IMA_FOWNER | IMA_FSUUID |
>  				     IMA_INMASK | IMA_EUID | IMA_PCR |
> -				     IMA_FSNAME | IMA_DIGSIG_REQUIRED |
> +				     IMA_FSNAME | IMA_GID | IMA_EGID |
> +				     IMA_FGROUP | IMA_DIGSIG_REQUIRED |
>  				     IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
>  				     IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
>  			return false;
> @@ -1186,7 +1235,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  
>  		if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID |
>  				     IMA_FOWNER | IMA_FSUUID | IMA_EUID |
> -				     IMA_PCR | IMA_FSNAME))
> +				     IMA_PCR | IMA_FSNAME | IMA_GID | IMA_EGID |
> +				     IMA_FGROUP))
>  			return false;
>  
>  		break;
> @@ -1195,7 +1245,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  			return false;
>  
>  		if (entry->flags & ~(IMA_FUNC | IMA_UID | IMA_PCR |
> -				     IMA_KEYRINGS))
> +				     IMA_KEYRINGS | IMA_GID))
>  			return false;
>  
>  		if (ima_rule_contains_lsm_cond(entry))
> @@ -1207,7 +1257,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  			return false;
>  
>  		if (entry->flags & ~(IMA_FUNC | IMA_UID | IMA_PCR |
> -				     IMA_LABEL))
> +				     IMA_LABEL | IMA_GID))

How about moving IMA_GID after IMA_UID?

>  			return false;
>  
>  		if (ima_rule_contains_lsm_cond(entry))
> @@ -1276,7 +1326,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  	struct audit_buffer *ab;
>  	char *from;
>  	char *p;
> -	bool uid_token;
> +	bool eid_token;

Took a moment to understand the reason for this change.   Adding a
comment on the line, like "either euid or egid" might have helped.  

>  	struct ima_template_desc *template_desc;
>  	int result = 0;
>  
> @@ -1284,9 +1334,13 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				       AUDIT_INTEGRITY_POLICY_RULE);
>  
>  	entry->uid = INVALID_UID;
> +	entry->gid = INVALID_GID;
>  	entry->fowner = INVALID_UID;
> +	entry->fgroup = INVALID_GID;
>  	entry->uid_op = &uid_eq;
> +	entry->gid_op = &gid_eq;
>  	entry->fowner_op = &uid_eq;
> +	entry->fgroup_op = &gid_eq;
>  	entry->action = UNKNOWN;
>  	while ((p = strsep(&rule, " \t")) != NULL) {
>  		substring_t args[MAX_OPT_ARGS];
> @@ -1504,12 +1558,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  			fallthrough;
>  		case Opt_uid_eq:
>  		case Opt_euid_eq:
> -			uid_token = (token == Opt_uid_eq) ||
> -				    (token == Opt_uid_gt) ||
> -				    (token == Opt_uid_lt);
> +			eid_token = (token == Opt_euid_eq) ||
> +				    (token == Opt_euid_gt) ||
> +				    (token == Opt_euid_lt);
>  
> -			ima_log_string_op(ab, uid_token ? "uid" : "euid",
> -					  args[0].from, entry->uid_op);
> +			ima_log_string_op(ab, eid_token ? "euid" : "uid",
> +					  args[0].from, token);
>  
>  			if (uid_valid(entry->uid)) {
>  				result = -EINVAL;
> @@ -1524,8 +1578,41 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				    (uid_t)lnum != lnum)
>  					result = -EINVAL;
>  				else
> -					entry->flags |= uid_token
> -					    ? IMA_UID : IMA_EUID;
> +					entry->flags |= eid_token
> +					    ? IMA_EUID : IMA_UID;
> +			}
> +			break;
> +		case Opt_gid_gt:
> +		case Opt_egid_gt:
> +			entry->gid_op = &gid_gt;
> +			fallthrough;
> +		case Opt_gid_lt:
> +		case Opt_egid_lt:
> +			if ((token == Opt_gid_lt) || (token == Opt_egid_lt))
> +				entry->gid_op = &gid_lt;
> +			fallthrough;
> +		case Opt_gid_eq:
> +		case Opt_egid_eq:
> +			eid_token = (token == Opt_egid_eq) ||
> +				    (token == Opt_egid_gt) ||
> +				    (token == Opt_egid_lt);
> +
> +			ima_log_string_op(ab, eid_token ? "egid" : "gid",
> +					  args[0].from, token);
> +
> +			if (gid_valid(entry->gid)) {
> +				result = -EINVAL;
> +				break;
> +			}
> +
> +			result = kstrtoul(args[0].from, 10, &lnum);
> +			if (!result) {
> +				entry->gid = make_kgid(current_user_ns(), (gid_t)lnum);
> +				if (!gid_valid(entry->gid) || (((gid_t)lnum) != lnum))

Example of where the indentation changes from original "uid" code.

> +					result = -EINVAL;
> +				else
> +					entry->flags |= eid_token
> +					    ? IMA_EGID : IMA_GID;
>  			}
>  			break;
>  		case Opt_fowner_gt:
> @@ -1536,8 +1623,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				entry->fowner_op = &uid_lt;
>  			fallthrough;
>  		case Opt_fowner_eq:
> -			ima_log_string_op(ab, "fowner", args[0].from,
> -					  entry->fowner_op);
> +			ima_log_string_op(ab, "fowner", args[0].from, token);
>  
>  			if (uid_valid(entry->fowner)) {
>  				result = -EINVAL;
> @@ -1553,6 +1639,30 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  					entry->flags |= IMA_FOWNER;
>  			}
>  			break;
> +		case Opt_fgroup_gt:
> +			entry->fgroup_op = &gid_gt;
> +			fallthrough;
> +		case Opt_fgroup_lt:
> +			if (token == Opt_fgroup_lt)
> +				entry->fgroup_op = &gid_lt;
> +			fallthrough;
> +		case Opt_fgroup_eq:
> +			ima_log_string_op(ab, "fgroup", args[0].from, token);
> +
> +			if (gid_valid(entry->fgroup)) {
> +				result = -EINVAL;
> +				break;
> +			}
> +
> +			result = kstrtoul(args[0].from, 10, &lnum);
> +			if (!result) {
> +				entry->fgroup = make_kgid(current_user_ns(), (gid_t)lnum);
> +				if (!gid_valid(entry->fgroup) || (((gid_t)lnum) != lnum))

and here

> +					result = -EINVAL;
> +				else
> +					entry->flags |= IMA_FGROUP;
> +			}
> +			break;
>  		case Opt_obj_user:
>  			ima_log_string(ab, "obj_user", args[0].from);
>  			result = ima_lsm_rule_init(entry, args,


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

      parent reply	other threads:[~2021-10-04 22:34 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-09 16:51 [LTP] [PATCH linux rebase] ima: add gid support Alex Henrie
2021-09-09 16:51 ` Alex Henrie
2021-09-09 16:51 ` [LTP] [PATCH ltp] IMA: Add tests for uid, gid, fowner, and fgroup options Alex Henrie
2021-09-09 16:51   ` Alex Henrie
2021-09-09 20:21   ` Petr Vorel
2021-09-09 20:21     ` Petr Vorel
2021-09-10  0:35     ` Alex Henrie
2021-09-10  0:35       ` Alex Henrie
2021-09-10  7:33       ` Petr Vorel
2021-09-10  7:33         ` Petr Vorel
2021-10-04 22:30 ` Mimi Zohar [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e6d38bb046c85ecf1eb76ba45b989fd6853c416a.camel@linux.ibm.com \
    --to=zohar@linux.ibm.com \
    --cc=alexh@vpitech.com \
    --cc=alexhenrie24@gmail.com \
    --cc=linux-integrity@vger.kernel.org \
    --cc=ltp@lists.linux.it \
    --cc=pvorel@suse.cz \
    --cc=veit@vpieng.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox