On 11/10/13 16:25, Joe Perches wrote:
> Printing kernel pointers via %pK has a minor defect when
> kptr_restrict is set to 2:  the pointer may be emitted
> as "pK-error" instead of all 0's when in an interrupt.

NAK. This is not a defect, as I explained earlier. It is really a defect
that it _doesn't_ print 'pK-error' in all cases. 'pK-error' is for
finding kernel bugs.

If a user sets kptr_restrict to 0 (or 2 with this patch), then pointer
values printed from interrupt handlers will appear as normal (all 0's in
kptr_restrict=2 case), so the user will not notice that the kernel code
is actually buggy. If they ever set kptr_restrict to 1 then they will
start seeing the 'pK-error' value. Since the default kptr_restrict
setting is now 0, it is less likely that users/developers will see the
'pK-error' message for buggy code.

~Ryan

> 
> Fix this defect, neaten the code, and correct the sysctl
> documentation.
> 
> Add missing documentation for 2 other uses: %pNF and %pV.
> 
> Trivially reduces vsprintf.o object size:
> 
> $ size lib/vsprintf.o*
>    text          data     bss     dec     hex filename
>   14536             6       0   14542    38ce lib/vsprintf.o.new
>   14568             6       0   14574    38ee lib/vsprintf.o.old
> 
> Signed-off-by: Joe Perches <j...@perches.com>
> ---
>  Documentation/sysctl/kernel.txt | 17 +++++++++--------
>  lib/vsprintf.c                  | 38 ++++++++++++++++++++++++--------------
>  2 files changed, 33 insertions(+), 22 deletions(-)
> 
> diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
> index 9d4c1d1..c17d5ca 100644
> --- a/Documentation/sysctl/kernel.txt
> +++ b/Documentation/sysctl/kernel.txt
> @@ -289,14 +289,15 @@ Default value is "/sbin/hotplug".
>  
>  kptr_restrict:
>  
> -This toggle indicates whether restrictions are placed on
> -exposing kernel addresses via /proc and other interfaces.  When
> -kptr_restrict is set to (0), there are no restrictions.  When
> -kptr_restrict is set to (1), the default, kernel pointers
> -printed using the %pK format specifier will be replaced with 0's
> -unless the user has CAP_SYSLOG.  When kptr_restrict is set to
> -(2), kernel pointers printed using %pK will be replaced with 0's
> -regardless of privileges.
> +This toggle indicates whether restrictions are placed on exposing kernel
> +addresses via /proc and other interfaces.
> +
> +When kptr_restrict is set to (0), the default, there are no restrictions.
> +When kptr_restrict is set to (1), kernel pointers printed using the %pK
> +format specifier will be replaced with 0's unless the user has CAP_SYSLOG
> +and effective user and group ids are equal to the real ids.
> +When kptr_restrict is set to (2), kernel pointers printed using %pK will
> +be replaced with 0's regardless of privileges.
>  
>  ==============================================================
>  
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 26559bd..ce55f52 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1301,21 +1301,28 @@ char *pointer(const char *fmt, char *buf, char *end, 
> void *ptr,
>                       va_end(va);
>                       return buf;
>               }
> -     case 'K':
> -             /*
> -              * %pK cannot be used in IRQ context because its test
> -              * for CAP_SYSLOG would be meaningless.
> -              */
> -             if (kptr_restrict && (in_irq() || in_serving_softirq() ||
> -                                   in_nmi())) {
> -                     if (spec.field_width == -1)
> -                             spec.field_width = default_width;
> -                     return string(buf, end, "pK-error", spec);
> -             }
> -             if (!((kptr_restrict == 0) ||
> -                   (kptr_restrict == 1 &&
> -                    has_capability_noaudit(current, CAP_SYSLOG))))
> +     case 'K':               /* see: Documentation/sysctl/kernel.txt */
> +             switch (kptr_restrict) {
> +             case 0:                 /* None (default) */
> +                     break;
> +             case 1:                 /* Restricted */
> +                     if (in_irq() || in_serving_softirq() || in_nmi()) {
> +                             /*
> +                              * This cannot be used in IRQ context because
> +                              * the test for CAP_SYSLOG would be meaningless
> +                              */
> +                             if (spec.field_width == -1)
> +                                     spec.field_width = default_width;
> +                             return string(buf, end, "pK-error", spec);
> +                     }
> +                     if (!has_capability_noaudit(current, CAP_SYSLOG))
> +                             ptr = NULL;
> +                     break;
> +             case 2:                 /* Never - Always emit 0 */
> +             default:
>                       ptr = NULL;
> +                     break;
> +             }
>               break;
>       case 'N':
>               switch (fmt[1]) {
> @@ -1574,6 +1581,9 @@ qualifier:
>   * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
>   * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
>   *   case.
> + * %pV recurse and output a struct va_format (const char *fmt, va_list *)
> + * %pK output a kernel address or 0 depending on sysctl kptr_restrict
> + * %NF output a netdev_features_t
>   * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
>   *           bytes of the input)
>   * %n is ignored
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to