ima: hook for integrity protection of symbolic links

This patch adds a new hook ima_link_check() to check integrity of
symbolic links.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
diff --git a/fs/namei.c b/fs/namei.c
index f3675e2..8c62e5d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -859,6 +859,9 @@
 			put_link(nd, link, *p);
 			return PTR_ERR(s);
 		}
+		error = ima_link_check(dentry, s);
+		if (unlikely(error))
+			goto out_put_nd_path;
 		if (*s == '/') {
 			set_root(nd);
 			path_put(&nd->path);
@@ -1943,7 +1946,7 @@
 	 * following mounts are sufficiently divergent that functions are
 	 * duplicated. Typically there is a function foo(), and its RCU
 	 * analogue, foo_rcu().
-	 *
+ 	 *
 	 * -ECHILD is the error number of choice (just to avoid clashes) that
 	 * is returned if some aspect of an rcu-walk fails. Such an error must
 	 * be handled by restarting a traditional ref-walk (which will always
@@ -4393,7 +4396,9 @@
 	if (IS_ERR(cookie))
 		return PTR_ERR(cookie);
 
-	res = readlink_copy(buffer, buflen, nd_get_link(&nd));
+	res = ima_link_check(dentry, nd_get_link(&nd));
+	if (!res)
+		res = readlink_copy(buffer, buflen, nd_get_link(&nd));
 	if (dentry->d_inode->i_op->put_link)
 		dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
 	return res;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index a980e0e..356e6af 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -85,6 +85,7 @@
 extern int ima_special_check(struct file *file, int mask);
 extern void ima_dir_update(struct path *dir, struct dentry *dentry,
 			   const char *link);
+extern int ima_link_check(struct dentry *dentry, const char *link);
 #else
 static inline int ima_dir_check(struct path *dir, int mask)
 {
@@ -102,6 +103,11 @@
 	return;
 }
 
+static inline int ima_link_check(struct dentry *dentry, const char *link)
+{
+	return 0;
+}
+
 #endif /* CONFIG_IMA_APPRAISE_DIRECTORIES */
 
 #endif /* _LINUX_IMA_H */