Check for setcap executables, as we already do for setuid and
setgid ones, and refuse to run them in the same way. BZ#335143.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13990 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index 6d525ee..2bba339 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -359,6 +359,18 @@
return (res == -1) ? (-1LL) : buf.size;
}
+SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
+{
+ SysRes res;
+#if defined(VGO_linux)
+ res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
+ attr_value, attr_value_len);
+#else
+ res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
+#endif
+ return res;
+}
+
Bool VG_(is_dir) ( const HChar* f )
{
struct vg_stat buf;
@@ -600,6 +612,13 @@
return VKI_EACCES;
}
+ res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
+ if (!sr_isError(res) && !allow_setuid) {
+ if (is_setuid)
+ *is_setuid = True;
+ return VKI_EACCES;
+ }
+
if (VG_(geteuid)() == st.uid) {
if (!(st.mode & VKI_S_IXUSR))
return VKI_EACCES;
diff --git a/coregrind/m_ume/main.c b/coregrind/m_ume/main.c
index 7be6df1..dc17d27 100644
--- a/coregrind/m_ume/main.c
+++ b/coregrind/m_ume/main.c
@@ -87,7 +87,7 @@
if (is_setuid && !VG_(clo_xml)) {
VG_(message)(Vg_UserMsg, "\n");
VG_(message)(Vg_UserMsg,
- "Warning: Can't execute setuid/setgid executable: %s\n",
+ "Warning: Can't execute setuid/setgid/setcap executable: %s\n",
exe_name);
VG_(message)(Vg_UserMsg, "Possible workaround: remove "
"--trace-children=yes, if in effect\n");
diff --git a/coregrind/pub_core_libcfile.h b/coregrind/pub_core_libcfile.h
index 7a8e25c..f27725b 100644
--- a/coregrind/pub_core_libcfile.h
+++ b/coregrind/pub_core_libcfile.h
@@ -49,6 +49,9 @@
/* Return the size of a file, or -1 in case of error */
extern Long VG_(fsize) ( Int fd );
+/* Lookup an extended attribute for a file */
+extern SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len );
+
/* Is the file a directory? */
extern Bool VG_(is_dir) ( const HChar* f );