All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT] More security subsystem fixes
@ 2012-01-19  5:32 James Morris
  2012-01-19  6:20 ` from-linux-security-module
  0 siblings, 1 reply; 5+ messages in thread
From: James Morris @ 2012-01-19  5:32 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-security-module, linux-kernel

Linus,

Please pull these fixes for 3.3.


The following changes since commit f59e842fc0871cd5baa213dc32e0ce8e5aaf4758:
  Linus Torvalds (1):
        Merge branch 'for-next-merge' of git://git.kernel.org/.../nab/target-pending

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git for-linus

David Howells (2):
      MPILIB: Add a missing ENOMEM check
      KEYS: Permit key_serial() to be called with a const key pointer

Mimi Zohar (2):
      ima: fix cred sparse warning
      keys: fix user_defined key sparse messages

 include/linux/key.h                 |    2 +-
 lib/mpi/mpicoder.c                  |    2 ++
 security/integrity/ima/ima_policy.c |    3 ++-
 security/keys/user_defined.c        |    6 +++---
 4 files changed, 8 insertions(+), 5 deletions(-)

---

commit 456a8167e94b66f406c27400a46a707b870452b0
Author: David Howells <dhowells@redhat.com>
Date:   Wed Jan 18 10:04:29 2012 +0000

    KEYS: Permit key_serial() to be called with a const key pointer
    
    Permit key_serial() to be called with a const key pointer.
    
    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: James Morris <jmorris@namei.org>

diff --git a/include/linux/key.h b/include/linux/key.h
index bfc014c..5253471 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -271,7 +271,7 @@ extern int keyring_add_key(struct key *keyring,
 
 extern struct key *key_lookup(key_serial_t id);
 
-static inline key_serial_t key_serial(struct key *key)
+static inline key_serial_t key_serial(const struct key *key)
 {
 	return key ? key->serial : 0;
 }

commit f6b24579d099ebb67f39cd7924a72a7eec0ce6ae
Author: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date:   Wed Jan 18 10:03:14 2012 +0000

    keys: fix user_defined key sparse messages
    
    Replace the rcu_assign_pointer() calls with rcu_assign_keypointer().
    
    Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: James Morris <jmorris@namei.org>

diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 69ff52c..2aee3c5 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -59,7 +59,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen)
 	/* attach the data */
 	upayload->datalen = datalen;
 	memcpy(upayload->data, data, datalen);
-	rcu_assign_pointer(key->payload.data, upayload);
+	rcu_assign_keypointer(key, upayload);
 	ret = 0;
 
 error:
@@ -98,7 +98,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
 	if (ret == 0) {
 		/* attach the new data, displacing the old */
 		zap = key->payload.data;
-		rcu_assign_pointer(key->payload.data, upayload);
+		rcu_assign_keypointer(key, upayload);
 		key->expiry = 0;
 	}
 
@@ -133,7 +133,7 @@ void user_revoke(struct key *key)
 	key_payload_reserve(key, 0);
 
 	if (upayload) {
-		rcu_assign_pointer(key->payload.data, NULL);
+		rcu_assign_keypointer(key, NULL);
 		kfree_rcu(upayload, rcu);
 	}
 }

commit 3db59dd93309710c40aaf1571c607cb0feef3ecb
Author: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date:   Tue Jan 17 22:11:28 2012 -0500

    ima: fix cred sparse warning
    
    Fix ima_policy.c sparse "warning: dereference of noderef expression"
    message, by accessing cred->uid using current_cred().
    
    Changelog v1:
    - Change __cred to just cred (based on David Howell's comment)
    
    Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
    Signed-off-by: James Morris <jmorris@namei.org>

diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index d661afb..d45061d 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -99,6 +99,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
 			    struct inode *inode, enum ima_hooks func, int mask)
 {
 	struct task_struct *tsk = current;
+	const struct cred *cred = current_cred();
 	int i;
 
 	if ((rule->flags & IMA_FUNC) && rule->func != func)
@@ -108,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
 	if ((rule->flags & IMA_FSMAGIC)
 	    && rule->fsmagic != inode->i_sb->s_magic)
 		return false;
-	if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
+	if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
 		return false;
 	for (i = 0; i < MAX_LSM_RULES; i++) {
 		int rc = 0;

commit 4bf1924c008dffdc154f82507b4052e49263a6f4
Author: David Howells <dhowells@redhat.com>
Date:   Wed Jan 18 10:03:54 2012 +0000

    MPILIB: Add a missing ENOMEM check
    
    Add a missing ENOMEM check.
    
    Signed-off-by: David Howells <dhowells@redhat.com>
    Acked-by: Mimi Zohar <zohar@us.ibm.com>
    Signed-off-by: James Morris <jmorris@namei.org>

diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index fe84bb9..716802b 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -255,6 +255,8 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
 	if (!n)
 		n++;		/* avoid zero length allocation */
 	p = buffer = kmalloc(n, GFP_KERNEL);
+	if (!p)
+		return NULL;
 
 	for (i = a->nlimbs - 1; i >= 0; i--) {
 		alimb = a->d[i];

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [GIT] More security subsystem fixes
  2012-01-19  5:32 [GIT] More security subsystem fixes James Morris
@ 2012-01-19  6:20 ` from-linux-security-module
  2012-01-19 14:21   ` Tetsuo Handa
  0 siblings, 1 reply; 5+ messages in thread
From: from-linux-security-module @ 2012-01-19  6:20 UTC (permalink / raw)
  To: jmorris; +Cc: linux-security-module, linux-kernel, torvalds

James Morris wrote:
>       MPILIB: Add a missing ENOMEM check
Maybe one more (shown below) with some random comments.



        for (i = a->nlimbs - 1; i >= 0; i--) {
                alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
                *p++ = alimb >> 24;
                *p++ = alimb >> 16;
                *p++ = alimb >> 8;
                *p++ = alimb;
#elif BYTES_PER_MPI_LIMB == 8
                *p++ = alimb >> 56;
                *p++ = alimb >> 48;
                *p++ = alimb >> 40;
                *p++ = alimb >> 32;
                *p++ = alimb >> 24;
                *p++ = alimb >> 16;
                *p++ = alimb >> 8;
                *p++ = alimb;
#else
#error please implement for this limb size.
#endif

Are such large bitshift guaranteed to work?



MPI do_encode_md(const void *sha_buffer, unsigned nbits)
{
(...snipped...)
        a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
	// Missing a != NULL check here.
        mpi_set_buffer(a, frame, nframe, 0);
        kfree(frame);
(...snipped...)
}

Is (nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB * sizeof(mpi_limb_t)
guaranteed not to overflow? Is nlimbs guaranteed to be not 0?

MPI mpi_alloc(unsigned nlimbs)
{
	mpi_alloc_limb_space(nlimbs)
	{
		mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
		{
		        size_t len = nlimbs * sizeof(mpi_limb_t);
		
		        return kmalloc(len, GFP_KERNEL);
		}
	}
}

There are several kmalloc(nlimbs * sizeof(mpi_limb_t)) calls.
Are they guaranteed not to overflow?

int mpi_resize(MPI a, unsigned nlimbs)
{
        void *p;

        if (nlimbs <= a->alloced)
                return 0;       /* no need to do it */

        if (a->d) {
		// Can use krealloc()?
                p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
                if (!p)
                        return -ENOMEM;
                memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t));
                kfree(a->d);
                a->d = p;
        } else {
                a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
                if (!a->d)
                        return -ENOMEM;
        }
        a->alloced = nlimbs;
        return 0;
}

Roughly browsing, it seems to me that this module assumes that kmalloc()
returns NULL if requested size was 0. It is OK for userspace, but I think we
should introduce and use a version of kmalloc() that returns NULL if requested
size was 0 (so that we can catch 0 byte allocation unless overflow).

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [GIT] More security subsystem fixes
  2012-01-19  6:20 ` from-linux-security-module
@ 2012-01-19 14:21   ` Tetsuo Handa
  2012-01-23  3:28     ` James Morris
  2012-01-25 12:26     ` Kasatkin, Dmitry
  0 siblings, 2 replies; 5+ messages in thread
From: Tetsuo Handa @ 2012-01-19 14:21 UTC (permalink / raw)
  To: jmorris; +Cc: linux-security-module, linux-kernel, torvalds

Tetsuo Handa wrote:
> James Morris wrote:
> >       MPILIB: Add a missing ENOMEM check
> Maybe one more (shown below) with some random comments.

Looked a bit more.



In lib/mpi/mpih-div.c:

mpi_limb_t
mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
               mpi_ptr_t np, mpi_size_t nsize, mpi_ptr_t dp, mpi_size_t dsize)
{
        mpi_limb_t most_significant_q_limb = 0;

        switch (dsize) {
        case 0:
                /* We are asked to divide by zero, so go ahead and do it!  (To make
                   the compiler not remove this statement, return the value.)  */
                return 1 / dsize;

What's this? Division by 0 in the kernel is no good.



In lib/mpi/mpicoder.c:

MPI do_encode_md(const void *sha_buffer, unsigned nbits)
{
(...snipped...)
        n = 0;
        frame[n++] = 0;
        frame[n++] = 1;         /* block type */
        i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;

        if (i <= 1) {
                pr_info("MPI: message digest encoding failed\n");
                kfree(frame);
                return a;
        }

        memset(frame + n, 0xff, i);
        n += i;
        frame[n++] = 0;
        memcpy(frame + n, &asn, asnlen);
        n += asnlen;
        memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
        n += SHA1_DIGEST_LENGTH;

        i = nframe;
        fr_pt = frame;

        if (n != nframe) {

What's this? i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; equals
nframe = i + SHA1_DIGEST_LENGTH + asnlen + 3; and this should be always true.
Also, i = nframe; seems to make no sense because i is no longer used.

                printk
                    ("MPI: message digest encoding failed, frame length is wrong\n");
                kfree(frame);
                return a;
        }

        a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);

Missing a != NULL check.

        mpi_set_buffer(a, frame, nframe, 0);
        kfree(frame);

        return a;
}



In lib/mpi/mpi-pow.c:

int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
{
(...snipped...)
        if (!msize)
                msize = 1 / msize;      /* provoke a signal */
(...snipped...)
}

Division by 0.



In lib/mpi/mpi-div.c:

int mpi_tdiv_q_2exp(MPI w, MPI u, unsigned count)
{
(...snipped...)
        usize = u->nlimbs;
        limb_cnt = count / BITS_PER_MPI_LIMB;
        wsize = usize - limb_cnt;
        if (limb_cnt >= usize)
                w->nlimbs = 0;
        else {
                mpi_ptr_t wp;
                mpi_ptr_t up;

                if (RESIZE_IF_NEEDED(w, wsize) < 0)
                        return -ENOMEM;
                wp = w->d;
                up = u->d;

                count %= BITS_PER_MPI_LIMB;
                if (count) {
                        mpihelp_rshift(wp, up + limb_cnt, wsize, count);
                        wsize -= !wp[wsize - 1];
(...snipped...)
}

Is wsize > 0 guaranteed?



Fixes (if any) will be needed to RHEL6's 2.6.32-220.2.1.el6 kernel as well.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [GIT] More security subsystem fixes
  2012-01-19 14:21   ` Tetsuo Handa
@ 2012-01-23  3:28     ` James Morris
  2012-01-25 12:26     ` Kasatkin, Dmitry
  1 sibling, 0 replies; 5+ messages in thread
From: James Morris @ 2012-01-23  3:28 UTC (permalink / raw)
  To: Tetsuo Handa, David Howells
  Cc: linux-security-module, linux-kernel, Linus Torvalds

On Thu, 19 Jan 2012, Tetsuo Handa wrote:

> mpi_limb_t
> mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
>                mpi_ptr_t np, mpi_size_t nsize, mpi_ptr_t dp, mpi_size_t dsize)
> {
>         mpi_limb_t most_significant_q_limb = 0;
> 
>         switch (dsize) {
>         case 0:
>                 /* We are asked to divide by zero, so go ahead and do it!  (To make
>                    the compiler not remove this statement, return the value.)  */
>                 return 1 / dsize;
> 
> What's this? Division by 0 in the kernel is no good.

David,

Do you know if this is triggerable from userland?


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [GIT] More security subsystem fixes
  2012-01-19 14:21   ` Tetsuo Handa
  2012-01-23  3:28     ` James Morris
@ 2012-01-25 12:26     ` Kasatkin, Dmitry
  1 sibling, 0 replies; 5+ messages in thread
From: Kasatkin, Dmitry @ 2012-01-25 12:26 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: jmorris, linux-security-module, linux-kernel, torvalds

On Thu, Jan 19, 2012 at 4:21 PM, Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> Tetsuo Handa wrote:
>> James Morris wrote:
>> >       MPILIB: Add a missing ENOMEM check
>> Maybe one more (shown below) with some random comments.
>
> Looked a bit more.
>
>
>
> In lib/mpi/mpih-div.c:
>
> mpi_limb_t
> mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
>               mpi_ptr_t np, mpi_size_t nsize, mpi_ptr_t dp, mpi_size_t dsize)
> {
>        mpi_limb_t most_significant_q_limb = 0;
>
>        switch (dsize) {
>        case 0:
>                /* We are asked to divide by zero, so go ahead and do it!  (To make
>                   the compiler not remove this statement, return the value.)  */
>                return 1 / dsize;
>
> What's this? Division by 0 in the kernel is no good.
>
>
>
> In lib/mpi/mpicoder.c:
>
> MPI do_encode_md(const void *sha_buffer, unsigned nbits)
> {
> (...snipped...)
>        n = 0;
>        frame[n++] = 0;
>        frame[n++] = 1;         /* block type */
>        i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
>
>        if (i <= 1) {
>                pr_info("MPI: message digest encoding failed\n");
>                kfree(frame);
>                return a;
>        }
>
>        memset(frame + n, 0xff, i);
>        n += i;
>        frame[n++] = 0;
>        memcpy(frame + n, &asn, asnlen);
>        n += asnlen;
>        memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
>        n += SHA1_DIGEST_LENGTH;
>
>        i = nframe;
>        fr_pt = frame;
>
>        if (n != nframe) {
>
> What's this? i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; equals
> nframe = i + SHA1_DIGEST_LENGTH + asnlen + 3; and this should be always true.

In fact n always equals to nframe, and this check is always false...


> Also, i = nframe; seems to make no sense because i is no longer used.
>
>                printk
>                    ("MPI: message digest encoding failed, frame length is wrong\n");
>                kfree(frame);
>                return a;
>        }
>
>        a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
>
> Missing a != NULL check.
>
>        mpi_set_buffer(a, frame, nframe, 0);
>        kfree(frame);
>
>        return a;
> }
>
>
>
> In lib/mpi/mpi-pow.c:
>
> int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
> {
> (...snipped...)
>        if (!msize)
>                msize = 1 / msize;      /* provoke a signal */
> (...snipped...)
> }
>
> Division by 0.
>
>
>
> In lib/mpi/mpi-div.c:
>
> int mpi_tdiv_q_2exp(MPI w, MPI u, unsigned count)
> {
> (...snipped...)
>        usize = u->nlimbs;
>        limb_cnt = count / BITS_PER_MPI_LIMB;
>        wsize = usize - limb_cnt;
>        if (limb_cnt >= usize)
>                w->nlimbs = 0;
>        else {
>                mpi_ptr_t wp;
>                mpi_ptr_t up;
>
>                if (RESIZE_IF_NEEDED(w, wsize) < 0)
>                        return -ENOMEM;
>                wp = w->d;
>                up = u->d;
>
>                count %= BITS_PER_MPI_LIMB;
>                if (count) {
>                        mpihelp_rshift(wp, up + limb_cnt, wsize, count);
>                        wsize -= !wp[wsize - 1];
> (...snipped...)
> }
>
> Is wsize > 0 guaranteed?
>
Should be, because of the check:
        if (limb_cnt >= usize)
                w->nlimbs = 0;
       else...


>
>
> Fixes (if any) will be needed to RHEL6's 2.6.32-220.2.1.el6 kernel as well.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-01-25 12:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-19  5:32 [GIT] More security subsystem fixes James Morris
2012-01-19  6:20 ` from-linux-security-module
2012-01-19 14:21   ` Tetsuo Handa
2012-01-23  3:28     ` James Morris
2012-01-25 12:26     ` Kasatkin, Dmitry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.