From: Dan Aloni <dan@kernelim.com>
To: linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com
Subject: [kernel-hardening] [PATCHv2 3/7] base64-armor: add bounds checking
Date: Sat, 13 Jan 2018 23:34:37 +0200 [thread overview]
Message-ID: <20180113213441.52047-4-dan@kernelim.com> (raw)
In-Reply-To: <20180113213441.52047-1-dan@kernelim.com>
Future use of the API can benefit from bounds checking.
Signed-off-by: Dan Aloni <dan@kernelim.com>
---
include/linux/base64-armor.h | 17 +++++++++++------
lib/base64-armor.c | 20 ++++++++++++++++++--
net/ceph/crypto.c | 2 +-
3 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/include/linux/base64-armor.h b/include/linux/base64-armor.h
index e5160c77bb2f..bb0b4491799e 100644
--- a/include/linux/base64-armor.h
+++ b/include/linux/base64-armor.h
@@ -8,11 +8,13 @@
* not contain newlines, depending on input length.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer.
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer.
+ * Returns the number of bytes written to the destination buffer, or
+ * an error of the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -22,19 +24,21 @@
*
* See base64_encode_buffer_bound below.
*/
-
-extern int base64_armor(char *dst, const char *src, const char *end);
+extern int base64_armor(char *dst, int dst_max, const char *src,
+ const char *end);
/**
* base64_unarmor: Perform armored base64 decoding.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer, or
- * -EINVAL if the source buffer contains invalid bytes.
+ * Returns the number of bytes written to the destination buffer,
+ * -EINVAL if the source buffer contains invalid bytes, or -ENOSPC
+ * if the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -43,7 +47,8 @@ extern int base64_armor(char *dst, const char *src, const char *end);
*
* See base64_decode_buffer_bound below.
*/
-extern int base64_unarmor(char *dst, const char *src, const char *end);
+extern int base64_unarmor(char *dst, int dst_max, const char *src,
+ const char *end);
/*
diff --git a/lib/base64-armor.c b/lib/base64-armor.c
index e07d25ac2850..f4a289f8da6a 100644
--- a/lib/base64-armor.c
+++ b/lib/base64-armor.c
@@ -33,7 +33,7 @@ static int decode_bits(char c)
return -EINVAL;
}
-int base64_armor(char *dst, const char *src, const char *end)
+int base64_armor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
int line = 0;
@@ -42,6 +42,8 @@ int base64_armor(char *dst, const char *src, const char *end)
unsigned char a, b, c;
a = *src++;
+ if (dst_max < 4)
+ return -ENOSPC;
*dst++ = encode_bits(a >> 2);
if (src < end) {
b = *src++;
@@ -62,17 +64,22 @@ int base64_armor(char *dst, const char *src, const char *end)
}
olen += 4;
line += 4;
+ dst_max -= 4;
+
if (line == 64) {
line = 0;
+ if (dst_max < 1)
+ return -ENOSPC;
*(dst++) = '\n';
olen++;
+ dst_max--;
}
}
return olen;
}
EXPORT_SYMBOL(base64_unarmor);
-int base64_unarmor(char *dst, const char *src, const char *end)
+int base64_unarmor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
@@ -92,13 +99,22 @@ int base64_unarmor(char *dst, const char *src, const char *end)
if (a < 0 || b < 0 || c < 0 || d < 0)
return -EINVAL;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = (a << 2) | (b >> 4);
+ dst_max--;
if (src[2] == '=')
return olen + 1;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((b & 15) << 4) | (c >> 2);
+ dst_max--;
if (src[3] == '=')
return olen + 2;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((c & 3) << 6) | d;
+ dst_max--;
olen += 3;
src += 4;
}
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 25e04e3b1aa4..f7c75368989a 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -116,7 +116,7 @@ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
buf = kmalloc(blen, GFP_NOFS);
if (!buf)
return -ENOMEM;
- blen = base64_unarmor(buf, inkey, inkey+inlen);
+ blen = base64_unarmor(buf, blen, inkey, inkey+inlen);
if (blen < 0) {
kfree(buf);
return blen;
--
2.14.3
WARNING: multiple messages have this Message-ID (diff)
From: Dan Aloni <dan@kernelim.com>
To: linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com
Subject: [PATCHv2 3/7] base64-armor: add bounds checking
Date: Sat, 13 Jan 2018 23:34:37 +0200 [thread overview]
Message-ID: <20180113213441.52047-4-dan@kernelim.com> (raw)
In-Reply-To: <20180113213441.52047-1-dan@kernelim.com>
Future use of the API can benefit from bounds checking.
Signed-off-by: Dan Aloni <dan@kernelim.com>
---
include/linux/base64-armor.h | 17 +++++++++++------
lib/base64-armor.c | 20 ++++++++++++++++++--
net/ceph/crypto.c | 2 +-
3 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/include/linux/base64-armor.h b/include/linux/base64-armor.h
index e5160c77bb2f..bb0b4491799e 100644
--- a/include/linux/base64-armor.h
+++ b/include/linux/base64-armor.h
@@ -8,11 +8,13 @@
* not contain newlines, depending on input length.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer.
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer.
+ * Returns the number of bytes written to the destination buffer, or
+ * an error of the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -22,19 +24,21 @@
*
* See base64_encode_buffer_bound below.
*/
-
-extern int base64_armor(char *dst, const char *src, const char *end);
+extern int base64_armor(char *dst, int dst_max, const char *src,
+ const char *end);
/**
* base64_unarmor: Perform armored base64 decoding.
*
* @dst: Beginning of the destination buffer.
+ * @dst_max: Maximum amount of bytes to write to the destination buffer.
* @src: Beginning of the source buffer
* @end: Sentinel for the source buffer, pointing one byte after the
* last byte to be encoded.
*
- * Returns the number of bytes written to the destination buffer, or
- * -EINVAL if the source buffer contains invalid bytes.
+ * Returns the number of bytes written to the destination buffer,
+ * -EINVAL if the source buffer contains invalid bytes, or -ENOSPC
+ * if the output buffer is insufficient in size.
*
* _Neither_ the input or output are expected to be NULL-terminated.
*
@@ -43,7 +47,8 @@ extern int base64_armor(char *dst, const char *src, const char *end);
*
* See base64_decode_buffer_bound below.
*/
-extern int base64_unarmor(char *dst, const char *src, const char *end);
+extern int base64_unarmor(char *dst, int dst_max, const char *src,
+ const char *end);
/*
diff --git a/lib/base64-armor.c b/lib/base64-armor.c
index e07d25ac2850..f4a289f8da6a 100644
--- a/lib/base64-armor.c
+++ b/lib/base64-armor.c
@@ -33,7 +33,7 @@ static int decode_bits(char c)
return -EINVAL;
}
-int base64_armor(char *dst, const char *src, const char *end)
+int base64_armor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
int line = 0;
@@ -42,6 +42,8 @@ int base64_armor(char *dst, const char *src, const char *end)
unsigned char a, b, c;
a = *src++;
+ if (dst_max < 4)
+ return -ENOSPC;
*dst++ = encode_bits(a >> 2);
if (src < end) {
b = *src++;
@@ -62,17 +64,22 @@ int base64_armor(char *dst, const char *src, const char *end)
}
olen += 4;
line += 4;
+ dst_max -= 4;
+
if (line == 64) {
line = 0;
+ if (dst_max < 1)
+ return -ENOSPC;
*(dst++) = '\n';
olen++;
+ dst_max--;
}
}
return olen;
}
EXPORT_SYMBOL(base64_unarmor);
-int base64_unarmor(char *dst, const char *src, const char *end)
+int base64_unarmor(char *dst, int dst_max, const char *src, const char *end)
{
int olen = 0;
@@ -92,13 +99,22 @@ int base64_unarmor(char *dst, const char *src, const char *end)
if (a < 0 || b < 0 || c < 0 || d < 0)
return -EINVAL;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = (a << 2) | (b >> 4);
+ dst_max--;
if (src[2] == '=')
return olen + 1;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((b & 15) << 4) | (c >> 2);
+ dst_max--;
if (src[3] == '=')
return olen + 2;
+ if (dst_max < 1)
+ return -ENOSPC;
*dst++ = ((c & 3) << 6) | d;
+ dst_max--;
olen += 3;
src += 4;
}
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 25e04e3b1aa4..f7c75368989a 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -116,7 +116,7 @@ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
buf = kmalloc(blen, GFP_NOFS);
if (!buf)
return -ENOMEM;
- blen = base64_unarmor(buf, inkey, inkey+inlen);
+ blen = base64_unarmor(buf, blen, inkey, inkey+inlen);
if (blen < 0) {
kfree(buf);
return blen;
--
2.14.3
next prev parent reply other threads:[~2018-01-13 21:34 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-13 21:34 [kernel-hardening] [PATCHv2 0/7] RFC: Public key encryption of dmesg by the kernel Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 1/7] crypto: fix memory leak in rsa-kcs1pad encryption Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 2/7] Move net/ceph/armor to lib/ and add docs Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-13 21:34 ` Dan Aloni [this message]
2018-01-13 21:34 ` [PATCHv2 3/7] base64-armor: add bounds checking Dan Aloni
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 4/7] certs: allow in-kernel access of trusted keys Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-15 9:11 ` [kernel-hardening] " David Howells
2018-01-15 9:11 ` David Howells
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 5/7] printk: allow kmsg to be encrypted using public key encryption Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-14 1:48 ` [kernel-hardening] " Sergey Senozhatsky
2018-01-14 1:48 ` Sergey Senozhatsky
2018-01-14 8:01 ` [kernel-hardening] " Dan Aloni
2018-01-14 8:01 ` Dan Aloni
2018-01-15 12:52 ` [kernel-hardening] " Steven Rostedt
2018-01-15 12:52 ` Steven Rostedt
2018-01-16 2:09 ` [kernel-hardening] " Sergey Senozhatsky
2018-01-16 2:09 ` Sergey Senozhatsky
2018-01-16 23:44 ` [kernel-hardening] " Daniel Micay
2018-01-17 15:01 ` Steven Rostedt
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 6/7] tools: add dmesg decryption program Dan Aloni
2018-01-13 21:34 ` Dan Aloni
2018-01-13 21:34 ` [kernel-hardening] [PATCHv2 7/7] docs: add dmesg encryption doc Dan Aloni
2018-01-13 21:34 ` Dan Aloni
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=20180113213441.52047-4-dan@kernelim.com \
--to=dan@kernelim.com \
--cc=kernel-hardening@lists.openwall.com \
--cc=linux-kernel@vger.kernel.org \
/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 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.