//! Smack label used for SECURITY_MANAGER_PATH_PUBLIC_RO paths (RO for all apps)
const char *const LABEL_FOR_APP_PUBLIC_RO_PATH = "User::Home";
-typedef std::function<bool(const FTSENT*)> LabelDecisionFn;
-
-static bool labelAll(const FTSENT *ftsent __attribute__((unused)))
-{
- return true;
-}
-
-static bool labelDirs(const FTSENT *ftsent)
-{
- // label only directories
- return (S_ISDIR(ftsent->fts_statp->st_mode));
-}
-
static inline void pathSetSmack(const char *path, const Smack::Label &label,
const char *xattr_name)
{
}
}
-static void dirSetSmack(const std::string &path, const Smack::Label &label,
- const char *xattr_name, LabelDecisionFn fn)
-{
- char *const path_argv[] = {const_cast<char *>(path.c_str()), NULL};
- FTSENT *ftsent;
+class PathSetup {
+public:
+ explicit PathSetup(bool transmute) : m_transmute(transmute) {}
+ void setup(const std::string &path)
+ {
+ // setting access label on everything in given directory and below
+ char *const path_argv[] = { const_cast<char*>(path.c_str()), NULL };
+ FTSENT *ftsent;
+
+ auto fts = makeUnique(fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL), fts_close);
+ if (!fts) {
+ LogError("fts_open failed.");
+ ThrowMsg(SmackException::FileError, "fts_open failed.");
+ }
- auto fts = makeUnique(fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL), fts_close);
- if (!fts) {
- LogError("fts_open failed.");
- ThrowMsg(SmackException::FileError, "fts_open failed.");
- }
+ while ((ftsent = fts_read(fts.get())) != NULL) {
+ /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
+ if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
+ LogError("FTS_ERR error or failed stat(2) (FTS_NS)");
+ ThrowMsg(SmackException::FileError, "FTS_ERR error or failed stat(2) (FTS_NS)");
+ }
- while ((ftsent = fts_read(fts.get())) != NULL) {
- /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
- if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
- LogError("FTS_ERR error or failed stat(2) (FTS_NS)");
- ThrowMsg(SmackException::FileError, "FTS_ERR error or failed stat(2) (FTS_NS)");
- }
+ /* avoid to tag directories two times */
+ if (ftsent->fts_info == FTS_D)
+ continue;
- /* avoid to tag directories two times */
- if (ftsent->fts_info == FTS_D)
- continue;
+ setupFile(ftsent);
+ }
- if (fn(ftsent))
- pathSetSmack(ftsent->fts_path, label, xattr_name);
+ /* If last call to fts_read() set errno, we need to return error. */
+ if ((errno != 0) && (ftsent == NULL))
+ LogAndThrowErrno(SmackException::FileError, "last fts_read");
}
- /* If last call to fts_read() set errno, we need to return error. */
- if ((errno != 0) && (ftsent == NULL))
- LogAndThrowErrno(SmackException::FileError, "last fts_read");
-}
+ virtual ~PathSetup() = default;
-static void labelDir(const std::string &path, const Smack::Label &label,
- bool set_transmutable)
-{
- // setting access label on everything in given directory and below
- dirSetSmack(path, label, XATTR_NAME_SMACK, labelAll);
+protected:
+ virtual void setupFile(FTSENT *ftsent) = 0;
- // setting transmute on dirs
- if (set_transmutable)
- dirSetSmack(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, labelDirs);
-}
+ bool m_transmute;
+};
+
+class SmackSetup: public PathSetup {
+public:
+ SmackSetup(const std::string label, bool transmute) :
+ PathSetup(transmute), m_label(std::move(label))
+ {
+ }
+
+protected:
+ void setupFile(FTSENT *ftsent) override
+ {
+ pathSetSmack(ftsent->fts_path, m_label, XATTR_NAME_SMACK);
+ if (m_transmute && S_ISDIR(ftsent->fts_statp->st_mode))
+ pathSetSmack(ftsent->fts_path, "TRUE", XATTR_NAME_SMACKTRANSMUTE);
+ }
+
+private:
+ std::string m_label;
+};
void setupPath(
const std::string &pkgName,
LogError("Path type not known.");
Throw(SmackException::InvalidPathType);
}
- if (follow_symlink) {
- labelDir(realPath(path), label, label_transmute);
- }
- return labelDir(path, label, label_transmute);
+ SmackSetup smack(label, label_transmute);
+ if (follow_symlink)
+ smack.setup(realPath(path));
+ smack.setup(path);
}
void setupPkgBasePath(const std::string &basePath)