forked from OSchip/llvm-project
[clang-tidy] Add a close-on-exec check on dup() in Android module.
Summary: dup() is better to be replaced by fcntl() to avoid file descriptor leakage. Differential Revision: https://reviews.llvm.org/D35364 llvm-svn: 310858
This commit is contained in:
parent
533d4c90bd
commit
56650e7fc5
|
@ -11,6 +11,7 @@
|
|||
#include "../ClangTidyModule.h"
|
||||
#include "../ClangTidyModuleRegistry.h"
|
||||
#include "CloexecCreatCheck.h"
|
||||
#include "CloexecDupCheck.h"
|
||||
#include "CloexecFopenCheck.h"
|
||||
#include "CloexecMemfdCreateCheck.h"
|
||||
#include "CloexecOpenCheck.h"
|
||||
|
@ -27,6 +28,7 @@ class AndroidModule : public ClangTidyModule {
|
|||
public:
|
||||
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
|
||||
CheckFactories.registerCheck<CloexecCreatCheck>("android-cloexec-creat");
|
||||
CheckFactories.registerCheck<CloexecDupCheck>("android-cloexec-dup");
|
||||
CheckFactories.registerCheck<CloexecFopenCheck>("android-cloexec-fopen");
|
||||
CheckFactories.registerCheck<CloexecMemfdCreateCheck>(
|
||||
"android-cloexec-memfd-create");
|
||||
|
|
|
@ -4,6 +4,7 @@ add_clang_library(clangTidyAndroidModule
|
|||
AndroidTidyModule.cpp
|
||||
CloexecCheck.cpp
|
||||
CloexecCreatCheck.cpp
|
||||
CloexecDupCheck.cpp
|
||||
CloexecFopenCheck.cpp
|
||||
CloexecMemfdCreateCheck.cpp
|
||||
CloexecOpenCheck.cpp
|
||||
|
|
|
@ -100,6 +100,15 @@ void CloexecCheck::insertStringFlag(
|
|||
ReplacementText);
|
||||
}
|
||||
|
||||
StringRef CloexecCheck::getSpellingArg(const MatchFinder::MatchResult &Result,
|
||||
int N) const {
|
||||
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
|
||||
const SourceManager &SM = *Result.SourceManager;
|
||||
return Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(MatchedCall->getArg(N)->getSourceRange()),
|
||||
SM, Result.Context->getLangOpts());
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
|
|
@ -86,6 +86,10 @@ protected:
|
|||
/// \param ArgPos The 0-based position of the flag argument.
|
||||
void insertStringFlag(const ast_matchers::MatchFinder::MatchResult &Result,
|
||||
const char Mode, const int ArgPos);
|
||||
|
||||
/// Helper function to get the spelling of a particular argument.
|
||||
StringRef getSpellingArg(const ast_matchers::MatchFinder::MatchResult &Result,
|
||||
int N) const;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//===--- CloexecDupCheck.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 "CloexecDupCheck.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace android {
|
||||
|
||||
void CloexecDupCheck::registerMatchers(MatchFinder *Finder) {
|
||||
registerMatchersImpl(Finder,
|
||||
functionDecl(returns(isInteger()), hasName("dup"),
|
||||
hasParameter(0, hasType(isInteger()))));
|
||||
}
|
||||
|
||||
void CloexecDupCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
const std::string &ReplacementText =
|
||||
(Twine("fcntl(") + getSpellingArg(Result, 0) + ", F_DUPFD_CLOEXEC)")
|
||||
.str();
|
||||
|
||||
replaceFunc(Result,
|
||||
"prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC",
|
||||
ReplacementText);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,36 @@
|
|||
//===--- CloexecDupCheck.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_DUP_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H
|
||||
|
||||
#include "CloexecCheck.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace android {
|
||||
|
||||
/// dup() is better to be replaced by fcntl(), which has close-on-exec flag.
|
||||
/// Find the usage of dup() and redirect user to use fcntl().
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html
|
||||
class CloexecDupCheck : public CloexecCheck {
|
||||
public:
|
||||
CloexecDupCheck(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_DUP_H
|
|
@ -70,6 +70,11 @@ Improvements to clang-tidy
|
|||
``AllowConditionalIntegerCasts`` -> ``AllowIntegerConditions``,
|
||||
``AllowConditionalPointerCasts`` -> ``AllowPointerConditions``.
|
||||
|
||||
- New `android-cloexec-dup
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html>`_ check
|
||||
|
||||
Detects usage of ``dup()``.
|
||||
|
||||
- New `android-cloexec-memfd_create
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd_create.html>`_ check
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
.. title:: clang-tidy - android-cloexec-dup
|
||||
|
||||
android-cloexec-dup
|
||||
===================
|
||||
|
||||
The usage of ``dup()`` is not recommended, it's better to use ``fcntl()``,
|
||||
which can set the close-on-exec flag. Otherwise, an opened sensitive file would
|
||||
remain open across a fork+exec to a lower-privileged SELinux domain.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
int fd = dup(oldfd);
|
||||
|
||||
// becomes
|
||||
|
||||
int fd = fcntl(oldfd, F_DUPFD_CLOEXEC);
|
|
@ -5,6 +5,7 @@ Clang-Tidy Checks
|
|||
|
||||
.. toctree::
|
||||
android-cloexec-creat
|
||||
android-cloexec-dup
|
||||
android-cloexec-fopen
|
||||
android-cloexec-memfd-create
|
||||
android-cloexec-open
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// RUN: %check_clang_tidy %s android-cloexec-dup %t
|
||||
|
||||
extern "C" int dup(int oldfd);
|
||||
void f() {
|
||||
dup(1);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC [android-cloexec-dup]
|
||||
// CHECK-FIXES: fcntl(1, F_DUPFD_CLOEXEC);
|
||||
int oldfd = 0;
|
||||
dup(oldfd);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer
|
||||
// CHECK-FIXES: fcntl(oldfd, F_DUPFD_CLOEXEC);
|
||||
}
|
||||
|
||||
namespace i {
|
||||
int dup(int oldfd);
|
||||
void g() {
|
||||
dup(0);
|
||||
int oldfd = 1;
|
||||
dup(oldfd);
|
||||
}
|
||||
} // namespace i
|
||||
|
||||
class C {
|
||||
public:
|
||||
int dup(int oldfd);
|
||||
void h() {
|
||||
dup(0);
|
||||
int oldfd = 1;
|
||||
dup(oldfd);
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue