[04/12] x86/CET: Extend arch_prctl syscall for CET control

Message ID 20180721142035.21059-5-hjl.tools@gmail.com
State Superseded
Headers show
Series
  • x86/CET: The last 12 patches to enable Intel CET
Related show

Commit Message

H.J. Lu July 21, 2018, 2:20 p.m.
/* CET features:
    IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT
    SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
  */

 /* Return CET features in unsigned long long *addr:
      features: addr[0].
      shadow stack base address: addr[1].
      shadow stack size: addr[2].
  */
 # define ARCH_CET_STATUS		0x3001
 /* Disable CET features in unsigned int features.  */
 # define ARCH_CET_DISABLE		0x3002
 /* Lock all CET features.  */
 # define ARCH_CET_LOCK			0x3003
 /* Allocate a new shadow stack with unsigned long long *addr:
      IN: requested shadow stack size: *addr.
      OUT: allocated shadow stack address: *addr.
  */
 # define ARCH_CET_ALLOC_SHSTK		0x3004
 /* Return legacy region bitmap info in unsigned long long *addr:
     address: addr[0].
     size: addr[1].
  */
 # define ARCH_CET_LEGACY_BITMAP	0x3005

	* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add
	bits/prctl.h.
	* sysdeps/unix/sysv/linux/bits/prctl.h: New file.
	* sysdeps/unix/sysv/linux/x86/bits/prctl.h: Likewise.
	* sysdeps/unix/sysv/linux/sys/prctl.h: Include <bits/prctl.h>.
	* sysdeps/unix/sysv/linux/x86/cpu-features.c: Include
	<sys/prctl.h>.
	(get_cet_status): Call arch_prctl with ARCH_CET_STATUS.
	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Include  <sys/prctl.h>.
	(dl_cet_allocate_legacy_bitmap): Call arch_prctl with
	ARCH_CET_LEGACY_BITMAP.
	(dl_cet_disable_cet): Call arch_prctl with ARCH_CET_DISABLE.
	(dl_cet_lock_cet): Call arch_prctl with ARCH_CET_LOCK.
	* sysdeps/x86/libc-start.c: Include <startup.h>.
---
 sysdeps/unix/sysv/linux/Makefile           |  3 +-
 sysdeps/unix/sysv/linux/bits/prctl.h       | 21 ++++++++++
 sysdeps/unix/sysv/linux/sys/prctl.h        |  1 +
 sysdeps/unix/sysv/linux/x86/bits/prctl.h   | 48 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86/cpu-features.c |  7 ++++
 sysdeps/unix/sysv/linux/x86/dl-cet.h       | 29 ++++++++++---
 sysdeps/x86/libc-start.c                   |  3 ++
 7 files changed, 105 insertions(+), 7 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/prctl.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/bits/prctl.h

-- 
2.17.1

Comments

Carlos O'Donell July 24, 2018, 3:05 a.m. | #1
On 07/21/2018 10:20 AM, H.J. Lu wrote:
>  /* CET features:

>     IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT

>     SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK

>   */

> 

>  /* Return CET features in unsigned long long *addr:

>       features: addr[0].

>       shadow stack base address: addr[1].

>       shadow stack size: addr[2].

>   */

>  # define ARCH_CET_STATUS		0x3001

>  /* Disable CET features in unsigned int features.  */

>  # define ARCH_CET_DISABLE		0x3002

>  /* Lock all CET features.  */

>  # define ARCH_CET_LOCK			0x3003

>  /* Allocate a new shadow stack with unsigned long long *addr:

>       IN: requested shadow stack size: *addr.

>       OUT: allocated shadow stack address: *addr.

>   */

>  # define ARCH_CET_ALLOC_SHSTK		0x3004

>  /* Return legacy region bitmap info in unsigned long long *addr:

>      address: addr[0].

>      size: addr[1].

>   */

>  # define ARCH_CET_LEGACY_BITMAP	0x3005

> 

> 	* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add

> 	bits/prctl.h.

> 	* sysdeps/unix/sysv/linux/bits/prctl.h: New file.

> 	* sysdeps/unix/sysv/linux/x86/bits/prctl.h: Likewise.

> 	* sysdeps/unix/sysv/linux/sys/prctl.h: Include <bits/prctl.h>.

> 	* sysdeps/unix/sysv/linux/x86/cpu-features.c: Include

> 	<sys/prctl.h>.

> 	(get_cet_status): Call arch_prctl with ARCH_CET_STATUS.

> 	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Include  <sys/prctl.h>.

> 	(dl_cet_allocate_legacy_bitmap): Call arch_prctl with

> 	ARCH_CET_LEGACY_BITMAP.

> 	(dl_cet_disable_cet): Call arch_prctl with ARCH_CET_DISABLE.

> 	(dl_cet_lock_cet): Call arch_prctl with ARCH_CET_LOCK.

> 	* sysdeps/x86/libc-start.c: Include <startup.h>.

> ---


The prctl.h values don't appear in any published kernel.

What's the status for these?

We can't ship them in the public prctl.h header unless they are already
in a public kernel or committed and basically ready to go out in a public
kernel.

You could rework this to only use the values internally and that would
be OK, since no user needs these yet, we are the primary CET user for
now.

>  sysdeps/unix/sysv/linux/Makefile           |  3 +-

>  sysdeps/unix/sysv/linux/bits/prctl.h       | 21 ++++++++++

>  sysdeps/unix/sysv/linux/sys/prctl.h        |  1 +

>  sysdeps/unix/sysv/linux/x86/bits/prctl.h   | 48 ++++++++++++++++++++++

>  sysdeps/unix/sysv/linux/x86/cpu-features.c |  7 ++++

>  sysdeps/unix/sysv/linux/x86/dl-cet.h       | 29 ++++++++++---

>  sysdeps/x86/libc-start.c                   |  3 ++

>  7 files changed, 105 insertions(+), 7 deletions(-)

>  create mode 100644 sysdeps/unix/sysv/linux/bits/prctl.h

>  create mode 100644 sysdeps/unix/sysv/linux/x86/bits/prctl.h

> 

> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile

> index f71cc39c7e..0bcc5287d9 100644

> --- a/sysdeps/unix/sysv/linux/Makefile

> +++ b/sysdeps/unix/sysv/linux/Makefile

> @@ -40,7 +40,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \

>  		  bits/signalfd.h bits/timerfd.h bits/epoll.h \

>  		  bits/socket_type.h bits/syscall.h bits/sysctl.h \

>  		  bits/mman-linux.h bits/mman-shared.h bits/ptrace-shared.h \

> -		  bits/siginfo-arch.h bits/siginfo-consts-arch.h

> +		  bits/siginfo-arch.h bits/siginfo-consts-arch.h \

> +		  bits/prctl.h


OK.

>  

>  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \

>  	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \

> diff --git a/sysdeps/unix/sysv/linux/bits/prctl.h b/sysdeps/unix/sysv/linux/bits/prctl.h

> new file mode 100644

> index 0000000000..be96218066

> --- /dev/null

> +++ b/sysdeps/unix/sysv/linux/bits/prctl.h

> @@ -0,0 +1,21 @@

> +/* Copyright (C) 2018 Free Software Foundation, Inc.

> +   This file is part of the GNU C Library.

> +

> +   The GNU C Library is free software; you can redistribute it and/or

> +   modify it under the terms of the GNU Lesser General Public

> +   License as published by the Free Software Foundation; either

> +   version 2.1 of the License, or (at your option) any later version.

> +

> +   The GNU C Library is distributed in the hope that it will be useful,

> +   but WITHOUT ANY WARRANTY; without even the implied warranty of

> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

> +   Lesser General Public License for more details.

> +

> +   You should have received a copy of the GNU Lesser General Public

> +   License along with the GNU C Library; if not, see

> +   <http://www.gnu.org/licenses/>.  */

> +

> +#ifndef _BITS_PRCTL_H

> +#define _BITS_PRCTL_H	1

> +

> +#endif  /* bits/prctl.h */


OK, add generic empty header.

> diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h

> index 683d16748f..6c4f643c75 100644

> --- a/sysdeps/unix/sysv/linux/sys/prctl.h

> +++ b/sysdeps/unix/sysv/linux/sys/prctl.h

> @@ -20,6 +20,7 @@

>  

>  #include <features.h>

>  #include <linux/prctl.h>  /*  The magic values come from here  */

> +#include <bits/prctl.h>


OK, include it.

>  

>  __BEGIN_DECLS

>  

> diff --git a/sysdeps/unix/sysv/linux/x86/bits/prctl.h b/sysdeps/unix/sysv/linux/x86/bits/prctl.h

> new file mode 100644

> index 0000000000..37e5fc8212

> --- /dev/null

> +++ b/sysdeps/unix/sysv/linux/x86/bits/prctl.h

> @@ -0,0 +1,48 @@

> +/* Copyright (C) 2018 Free Software Foundation, Inc.

> +   This file is part of the GNU C Library.

> +

> +   The GNU C Library is free software; you can redistribute it and/or

> +   modify it under the terms of the GNU Lesser General Public

> +   License as published by the Free Software Foundation; either

> +   version 2.1 of the License, or (at your option) any later version.

> +

> +   The GNU C Library is distributed in the hope that it will be useful,

> +   but WITHOUT ANY WARRANTY; without even the implied warranty of

> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

> +   Lesser General Public License for more details.

> +

> +   You should have received a copy of the GNU Lesser General Public

> +   License along with the GNU C Library; if not, see

> +   <http://www.gnu.org/licenses/>.  */

> +

> +#ifndef _BITS_PRCTL_H

> +#define _BITS_PRCTL_H	1

> +

> +#ifndef ARCH_CET_STATUS

> +/* CET features:

> +   IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT

> +   SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK

> + */

> +/* Return CET features in unsigned long long *addr:

> +     features: addr[0].

> +     shadow stack base address: addr[1].

> +     shadow stack size: addr[2].

> + */

> +# define ARCH_CET_STATUS	0x3001


OK.

> +/* Disable CET features in unsigned int features.  */

> +# define ARCH_CET_DISABLE	0x3002


OK.

> +/* Lock all CET features.  */

> +# define ARCH_CET_LOCK		0x3003'


OK.

> +/* Allocate a new shadow stack with unsigned long long *addr:

> +     IN: requested shadow stack size: *addr.

> +     OUT: allocated shadow stack address: *addr.

> + */

> +# define ARCH_CET_ALLOC_SHSTK	0x3004


OK.

> +/* Return legacy region bitmap info in unsigned long long *addr:

> +     address: addr[0].

> +     size: addr[1].

> + */

> +# define ARCH_CET_LEGACY_BITMAP	0x3005


OK.

> +#endif /* ARCH_CET_STATUS */

> +

> +#endif  /* bits/prctl.h */

> diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c

> index 7c9df9b794..c7c59055dc 100644

> --- a/sysdeps/unix/sysv/linux/x86/cpu-features.c

> +++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c

> @@ -17,9 +17,16 @@

>     <http://www.gnu.org/licenses/>.  */

>  

>  #if CET_ENABLED

> +# include <sys/prctl.h>

> +

>  static inline int __attribute__ ((always_inline))

>  get_cet_status (void)

>  {

> +  unsigned long long cet_status[3];

> +  INTERNAL_SYSCALL_DECL (err);

> +  if (INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_STATUS,

> +			cet_status) == 0)

> +    return cet_status[0];


OK.

>    return 0;

>  }

>  

> diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h

> index ae81e2f2ca..787368292d 100644

> --- a/sysdeps/unix/sysv/linux/x86/dl-cet.h

> +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h

> @@ -15,23 +15,40 @@

>     License along with the GNU C Library; if not, see

>     <http://www.gnu.org/licenses/>.  */

>  

> +#include <sys/prctl.h>

> +

>  static inline int __attribute__ ((always_inline))

>  dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)

>  {

> -  /* FIXME: Need syscall support.  */

> -  return -1;

> +  /* Allocate legacy bitmap.  */

> +  INTERNAL_SYSCALL_DECL (err);

> +#ifdef __LP64__

> +  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2,

> +				 ARCH_CET_LEGACY_BITMAP, legacy_bitmap);

> +#else

> +  unsigned long long legacy_bitmap_u64[2];

> +  int res = INTERNAL_SYSCALL (arch_prctl, err, 2,

> +			      ARCH_CET_LEGACY_BITMAP, legacy_bitmap_u64);

> +  if (res == 0)

> +    {

> +      legacy_bitmap[0] = legacy_bitmap_u64[0];

> +      legacy_bitmap[1] = legacy_bitmap_u64[1];

> +    }

> +  return res;


OK.

> +#endif

>  }

>  

>  static inline int __attribute__ ((always_inline))

>  dl_cet_disable_cet (unsigned int cet_feature)

>  {

> -  /* FIXME: Need syscall support.  */

> -  return -1;

> +  INTERNAL_SYSCALL_DECL (err);

> +  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_DISABLE,

> +				 cet_feature);


OK.

>  }

>  

>  static inline int __attribute__ ((always_inline))

>  dl_cet_lock_cet (void)

>  {

> -  /* FIXME: Need syscall support.  */

> -  return -1;

> +  INTERNAL_SYSCALL_DECL (err);

> +  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_LOCK, 0);


OK.

>  }

> diff --git a/sysdeps/x86/libc-start.c b/sysdeps/x86/libc-start.c

> index 43aba9d061..eb5335c154 100644

> --- a/sysdeps/x86/libc-start.c

> +++ b/sysdeps/x86/libc-start.c

> @@ -16,6 +16,9 @@

>     <http://www.gnu.org/licenses/>.  */

>  

>  #ifndef SHARED

> +/* Define I386_USE_SYSENTER to support syscall during startup in static

> +   PIE.  */

> +# include <startup.h>


OK.

>  # include <ldsodefs.h>

>  # include <cpu-features.h>

>  # include <cpu-features.c>

>

Patch

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index f71cc39c7e..0bcc5287d9 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -40,7 +40,8 @@  sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
 		  bits/signalfd.h bits/timerfd.h bits/epoll.h \
 		  bits/socket_type.h bits/syscall.h bits/sysctl.h \
 		  bits/mman-linux.h bits/mman-shared.h bits/ptrace-shared.h \
-		  bits/siginfo-arch.h bits/siginfo-consts-arch.h
+		  bits/siginfo-arch.h bits/siginfo-consts-arch.h \
+		  bits/prctl.h
 
 tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
diff --git a/sysdeps/unix/sysv/linux/bits/prctl.h b/sysdeps/unix/sysv/linux/bits/prctl.h
new file mode 100644
index 0000000000..be96218066
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/prctl.h
@@ -0,0 +1,21 @@ 
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_PRCTL_H
+#define _BITS_PRCTL_H	1
+
+#endif  /* bits/prctl.h */
diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h
index 683d16748f..6c4f643c75 100644
--- a/sysdeps/unix/sysv/linux/sys/prctl.h
+++ b/sysdeps/unix/sysv/linux/sys/prctl.h
@@ -20,6 +20,7 @@ 
 
 #include <features.h>
 #include <linux/prctl.h>  /*  The magic values come from here  */
+#include <bits/prctl.h>
 
 __BEGIN_DECLS
 
diff --git a/sysdeps/unix/sysv/linux/x86/bits/prctl.h b/sysdeps/unix/sysv/linux/x86/bits/prctl.h
new file mode 100644
index 0000000000..37e5fc8212
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/bits/prctl.h
@@ -0,0 +1,48 @@ 
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_PRCTL_H
+#define _BITS_PRCTL_H	1
+
+#ifndef ARCH_CET_STATUS
+/* CET features:
+   IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT
+   SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
+ */
+/* Return CET features in unsigned long long *addr:
+     features: addr[0].
+     shadow stack base address: addr[1].
+     shadow stack size: addr[2].
+ */
+# define ARCH_CET_STATUS	0x3001
+/* Disable CET features in unsigned int features.  */
+# define ARCH_CET_DISABLE	0x3002
+/* Lock all CET features.  */
+# define ARCH_CET_LOCK		0x3003
+/* Allocate a new shadow stack with unsigned long long *addr:
+     IN: requested shadow stack size: *addr.
+     OUT: allocated shadow stack address: *addr.
+ */
+# define ARCH_CET_ALLOC_SHSTK	0x3004
+/* Return legacy region bitmap info in unsigned long long *addr:
+     address: addr[0].
+     size: addr[1].
+ */
+# define ARCH_CET_LEGACY_BITMAP	0x3005
+#endif /* ARCH_CET_STATUS */
+
+#endif  /* bits/prctl.h */
diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
index 7c9df9b794..c7c59055dc 100644
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
@@ -17,9 +17,16 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #if CET_ENABLED
+# include <sys/prctl.h>
+
 static inline int __attribute__ ((always_inline))
 get_cet_status (void)
 {
+  unsigned long long cet_status[3];
+  INTERNAL_SYSCALL_DECL (err);
+  if (INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_STATUS,
+			cet_status) == 0)
+    return cet_status[0];
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
index ae81e2f2ca..787368292d 100644
--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
@@ -15,23 +15,40 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <sys/prctl.h>
+
 static inline int __attribute__ ((always_inline))
 dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  /* Allocate legacy bitmap.  */
+  INTERNAL_SYSCALL_DECL (err);
+#ifdef __LP64__
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2,
+				 ARCH_CET_LEGACY_BITMAP, legacy_bitmap);
+#else
+  unsigned long long legacy_bitmap_u64[2];
+  int res = INTERNAL_SYSCALL (arch_prctl, err, 2,
+			      ARCH_CET_LEGACY_BITMAP, legacy_bitmap_u64);
+  if (res == 0)
+    {
+      legacy_bitmap[0] = legacy_bitmap_u64[0];
+      legacy_bitmap[1] = legacy_bitmap_u64[1];
+    }
+  return res;
+#endif
 }
 
 static inline int __attribute__ ((always_inline))
 dl_cet_disable_cet (unsigned int cet_feature)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  INTERNAL_SYSCALL_DECL (err);
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_DISABLE,
+				 cet_feature);
 }
 
 static inline int __attribute__ ((always_inline))
 dl_cet_lock_cet (void)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  INTERNAL_SYSCALL_DECL (err);
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_LOCK, 0);
 }
diff --git a/sysdeps/x86/libc-start.c b/sysdeps/x86/libc-start.c
index 43aba9d061..eb5335c154 100644
--- a/sysdeps/x86/libc-start.c
+++ b/sysdeps/x86/libc-start.c
@@ -16,6 +16,9 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef SHARED
+/* Define I386_USE_SYSENTER to support syscall during startup in static
+   PIE.  */
+# include <startup.h>
 # include <ldsodefs.h>
 # include <cpu-features.h>
 # include <cpu-features.c>