[clang-tidy] Add a close-on-exec check on epoll_create1() in Android module.

Summary:
epoll_create1() is better to set EPOLL_CLOEXEC flag to avoid file descriptor leakage.

Differential Revision: https://reviews.llvm.org/D35365

llvm-svn: 311028
This commit is contained in:
Chih-Hung Hsieh 2017-08-16 17:53:12 +00:00
parent 5ac20c9c25
commit 3be4ecb15b
8 changed files with 156 additions and 0 deletions

View File

@ -13,6 +13,7 @@
#include "CloexecAccept4Check.h"
#include "CloexecAcceptCheck.h"
#include "CloexecCreatCheck.h"
#include "CloexecEpollCreate1Check.h"
#include "CloexecDupCheck.h"
#include "CloexecFopenCheck.h"
#include "CloexecInotifyInit1Check.h"
@ -34,6 +35,8 @@ public:
CheckFactories.registerCheck<CloexecAccept4Check>("android-cloexec-accept4");
CheckFactories.registerCheck<CloexecAcceptCheck>("android-cloexec-accept");
CheckFactories.registerCheck<CloexecCreatCheck>("android-cloexec-creat");
CheckFactories.registerCheck<CloexecEpollCreate1Check>(
"android-cloexec-epoll-create1");
CheckFactories.registerCheck<CloexecDupCheck>("android-cloexec-dup");
CheckFactories.registerCheck<CloexecFopenCheck>("android-cloexec-fopen");
CheckFactories.registerCheck<CloexecInotifyInitCheck>(

View File

@ -6,6 +6,7 @@ add_clang_library(clangTidyAndroidModule
CloexecAcceptCheck.cpp
CloexecCheck.cpp
CloexecCreatCheck.cpp
CloexecEpollCreate1Check.cpp
CloexecDupCheck.cpp
CloexecFopenCheck.cpp
CloexecInotifyInit1Check.cpp

View File

@ -0,0 +1,33 @@
//===--- CloexecEpollCreate1Check.cpp - clang-tidy-------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecEpollCreate1Check.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecEpollCreate1Check::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("epoll_create1"),
hasParameter(0, hasType(isInteger()))));
}
void CloexecEpollCreate1Check::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, /*MarcoFlag=*/"EPOLL_CLOEXEC", /*ArgPos=*/0);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,35 @@
//===--- CloexecEpollCreate1Check.h - clang-tidy-----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses epoll_create1() without using the EPOLL_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create1.html
class CloexecEpollCreate1Check : public CloexecCheck {
public:
CloexecEpollCreate1Check(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H

View File

@ -91,6 +91,12 @@ Improvements to clang-tidy
Detects usage of ``inotify_init()``.
- New `android-cloexec-epoll-create1
<http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create1.html>`_ check
Checks if the required file flag ``EPOLL_CLOEXEC`` is present in the argument of
``epoll_create1()``.
- New `android-cloexec-memfd_create
<http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd_create.html>`_ check

View File

@ -0,0 +1,18 @@
.. title:: clang-tidy - android-cloexec-epoll-create1
android-cloexec-epoll-create1
=============================
``epoll_create1()`` should include ``EPOLL_CLOEXEC`` in its type argument to
avoid the file descriptor leakage. Without this flag, an opened sensitive file
would remain open across a fork+exec to a lower-privileged SELinux domain.
Examples:
.. code-block:: c++
epoll_create1(0);
// becomes
epoll_create1(EPOLL_CLOEXEC);

View File

@ -7,6 +7,7 @@ Clang-Tidy Checks
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
android-cloexec-epoll-create1
android-cloexec-dup
android-cloexec-fopen
android-cloexec-inotify-init

View File

@ -0,0 +1,59 @@
// RUN: %check_clang_tidy %s android-cloexec-epoll-create1 %t
#define __O_CLOEXEC 3
#define EPOLL_CLOEXEC __O_CLOEXEC
#define TEMP_FAILURE_RETRY(exp) \
({ \
int _rc; \
do { \
_rc = (exp); \
} while (_rc == -1); \
})
extern "C" int epoll_create1(int flags);
void a() {
epoll_create1(0);
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1' should use EPOLL_CLOEXEC where possible [android-cloexec-epoll-create1]
// CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
TEMP_FAILURE_RETRY(epoll_create1(0));
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
// CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
}
void f() {
epoll_create1(3);
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'epoll_create1'
// CHECK-FIXES: epoll_create1(EPOLL_CLOEXEC);
TEMP_FAILURE_RETRY(epoll_create1(3));
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 'epoll_create1'
// CHECK-FIXES: TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
int flag = 0;
epoll_create1(EPOLL_CLOEXEC);
TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
}
namespace i {
int epoll_create1(int flags);
void d() {
epoll_create1(0);
TEMP_FAILURE_RETRY(epoll_create1(0));
}
} // namespace i
void e() {
epoll_create1(EPOLL_CLOEXEC);
TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
}
class G {
public:
int epoll_create1(int flags);
void d() {
epoll_create1(EPOLL_CLOEXEC);
TEMP_FAILURE_RETRY(epoll_create1(EPOLL_CLOEXEC));
}
};