diff mbox

[V11,2/5] vsprintf: refactor %pK code out of pointer()

Message ID 1511921105-3647-3-git-send-email-me@tobin.cc (mailing list archive)
State New, archived
Headers show

Commit Message

Tobin Harding Nov. 29, 2017, 2:05 a.m. UTC
Currently code to handle %pK is all within the switch statement in
pointer(). This is the wrong level of abstraction. Each of the other switch
clauses call a helper function, pK should do the same.

Refactor code out of pointer() to new function restricted_pointer().

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
 lib/vsprintf.c | 97 ++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 54 insertions(+), 43 deletions(-)

Comments

Steven Rostedt Nov. 29, 2017, 2:39 a.m. UTC | #1
On Wed, 29 Nov 2017 13:05:02 +1100
"Tobin C. Harding" <me@tobin.cc> wrote:

> +		/*
> +		 * kptr_restrict==1 cannot be used in IRQ context
> +		 * because its test for CAP_SYSLOG would be meaningless.
> +		 */
> +		if (in_irq() || in_serving_softirq() || in_nmi())

This could be replaced with:

		if (!in_task())

Which is actually more efficient.

-- Steve

> +			return string(buf, end, "pK-error", spec);
Tobin Harding Nov. 29, 2017, 4:27 a.m. UTC | #2
On Tue, Nov 28, 2017 at 09:39:57PM -0500, Steven Rostedt wrote:
> On Wed, 29 Nov 2017 13:05:02 +1100
> "Tobin C. Harding" <me@tobin.cc> wrote:
> 
> > +		/*
> > +		 * kptr_restrict==1 cannot be used in IRQ context
> > +		 * because its test for CAP_SYSLOG would be meaningless.
> > +		 */
> > +		if (in_irq() || in_serving_softirq() || in_nmi())
> 
> This could be replaced with:
> 
> 		if (!in_task())
> 
> Which is actually more efficient.

thanks for the comment Steve. At this late stage in the game do you mind
if I don't include this change in this set. The code line in question is
only in the series because of refactoring. I'm comfortable arguing that
improving efficiency is out of scope ;)

thanks,
Tobin.
Steven Rostedt Nov. 29, 2017, 11:54 a.m. UTC | #3
On Wed, 29 Nov 2017 15:27:46 +1100
"Tobin C. Harding" <me@tobin.cc> wrote:

> On Tue, Nov 28, 2017 at 09:39:57PM -0500, Steven Rostedt wrote:
> > On Wed, 29 Nov 2017 13:05:02 +1100
> > "Tobin C. Harding" <me@tobin.cc> wrote:
> >   
> > > +		/*
> > > +		 * kptr_restrict==1 cannot be used in IRQ context
> > > +		 * because its test for CAP_SYSLOG would be meaningless.
> > > +		 */
> > > +		if (in_irq() || in_serving_softirq() || in_nmi())  
> > 
> > This could be replaced with:
> > 
> > 		if (!in_task())
> > 
> > Which is actually more efficient.  
> 
> thanks for the comment Steve. At this late stage in the game do you mind
> if I don't include this change in this set. The code line in question is
> only in the series because of refactoring. I'm comfortable arguing that
> improving efficiency is out of scope ;)

No problem. In fact, I can send this as a separate patch myself, on top
of your series.

-- Steve
diff mbox

Patch

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 1746bae94d41..8dc5cf85cef4 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1343,6 +1343,59 @@  char *uuid_string(char *buf, char *end, const u8 *addr,
 	return string(buf, end, uuid, spec);
 }
 
+int kptr_restrict __read_mostly;
+
+static noinline_for_stack
+char *restricted_pointer(char *buf, char *end, const void *ptr,
+			 struct printf_spec spec)
+{
+	spec.base = 16;
+	spec.flags |= SMALL;
+	if (spec.field_width == -1) {
+		spec.field_width = 2 * sizeof(ptr);
+		spec.flags |= ZEROPAD;
+	}
+
+	switch (kptr_restrict) {
+	case 0:
+		/* Always print %pK values */
+		break;
+	case 1: {
+		const struct cred *cred;
+
+		/*
+		 * kptr_restrict==1 cannot be used in IRQ context
+		 * because its test for CAP_SYSLOG would be meaningless.
+		 */
+		if (in_irq() || in_serving_softirq() || in_nmi())
+			return string(buf, end, "pK-error", spec);
+
+		/*
+		 * Only print the real pointer value if the current
+		 * process has CAP_SYSLOG and is running with the
+		 * same credentials it started with. This is because
+		 * access to files is checked at open() time, but %pK
+		 * checks permission at read() time. We don't want to
+		 * leak pointer values if a binary opens a file using
+		 * %pK and then elevates privileges before reading it.
+		 */
+		cred = current_cred();
+		if (!has_capability_noaudit(current, CAP_SYSLOG) ||
+		    !uid_eq(cred->euid, cred->uid) ||
+		    !gid_eq(cred->egid, cred->gid))
+			ptr = NULL;
+		break;
+	}
+	case 2:
+	default:
+		/* Always print 0's for %pK */
+		ptr = NULL;
+		break;
+	}
+
+	return number(buf, end, (unsigned long)ptr, spec);
+}
+
 static noinline_for_stack
 char *netdev_bits(char *buf, char *end, const void *addr, const char *fmt)
 {
@@ -1591,8 +1644,6 @@  char *device_node_string(char *buf, char *end, struct device_node *dn,
 	return widen_string(buf, buf - buf_start, end, spec);
 }
 
-int kptr_restrict __read_mostly;
-
 /*
  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
  * by an extra set of alphanumeric characters that are extended format
@@ -1792,47 +1843,7 @@  char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			return buf;
 		}
 	case 'K':
-		switch (kptr_restrict) {
-		case 0:
-			/* Always print %pK values */
-			break;
-		case 1: {
-			const struct cred *cred;
-
-			/*
-			 * kptr_restrict==1 cannot be used in IRQ context
-			 * because its test for CAP_SYSLOG would be meaningless.
-			 */
-			if (in_irq() || in_serving_softirq() || in_nmi()) {
-				if (spec.field_width == -1)
-					spec.field_width = default_width;
-				return string(buf, end, "pK-error", spec);
-			}
-
-			/*
-			 * Only print the real pointer value if the current
-			 * process has CAP_SYSLOG and is running with the
-			 * same credentials it started with. This is because
-			 * access to files is checked at open() time, but %pK
-			 * checks permission at read() time. We don't want to
-			 * leak pointer values if a binary opens a file using
-			 * %pK and then elevates privileges before reading it.
-			 */
-			cred = current_cred();
-			if (!has_capability_noaudit(current, CAP_SYSLOG) ||
-			    !uid_eq(cred->euid, cred->uid) ||
-			    !gid_eq(cred->egid, cred->gid))
-				ptr = NULL;
-			break;
-		}
-		case 2:
-		default:
-			/* Always print 0's for %pK */
-			ptr = NULL;
-			break;
-		}
-		break;
-
+		return restricted_pointer(buf, end, ptr, spec);
 	case 'N':
 		return netdev_bits(buf, end, ptr, fmt);
 	case 'a':