Created
April 17, 2016 04:29
-
-
Save eru/13baeaabe6051b08c07a79d04442e309 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git linux/control.c linux/control.c | |
index 79716bd..2815f4f 100644 | |
--- linux/control.c | |
+++ linux/control.c | |
@@ -208,9 +208,11 @@ SetupProcDevice(void) | |
VMBlockSetProcEntryOwner(controlProcMountpoint); | |
/* Create /proc/fs/vmblock/dev */ | |
- controlProcEntry = create_proc_entry(VMBLOCK_CONTROL_DEVNAME, | |
- VMBLOCK_CONTROL_MODE, | |
- controlProcDirEntry); | |
+ controlProcEntry = proc_create(VMBLOCK_CONTROL_DEVNAME, | |
+ VMBLOCK_CONTROL_MODE, | |
+ controlProcDirEntry, | |
+ &ControlFileOps); | |
+ | |
if (!controlProcEntry) { | |
Warning("SetupProcDevice: could not create " VMBLOCK_DEVICE "\n"); | |
remove_proc_entry(VMBLOCK_CONTROL_MOUNTPOINT, controlProcDirEntry); | |
@@ -218,7 +220,10 @@ SetupProcDevice(void) | |
return -EINVAL; | |
} | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
controlProcEntry->proc_fops = &ControlFileOps; | |
+#endif | |
+ | |
return 0; | |
} | |
@@ -282,18 +287,24 @@ ExecuteBlockOp(const char __user *buf, // IN: buffer with name | |
int i; | |
int retval; | |
- name = getname(buf); | |
+ name = __getname(); | |
if (IS_ERR(name)) { | |
return PTR_ERR(name); | |
} | |
+ i = strncpy_from_user(name, buf, PATH_MAX); | |
+ if (i < 0 || i == PATH_MAX) { | |
+ __putname(name); | |
+ return -EINVAL; | |
+ } | |
+ | |
for (i = strlen(name) - 1; i >= 0 && name[i] == '/'; i--) { | |
name[i] = '\0'; | |
} | |
retval = i < 0 ? -EINVAL : blockOp(name, blocker); | |
- putname(name); | |
+ __putname(name); | |
return retval; | |
} | |
diff --git linux/dentry.c linux/dentry.c | |
index 05ea95a..09ce15b 100644 | |
--- linux/dentry.c | |
+++ linux/dentry.c | |
@@ -32,7 +32,11 @@ | |
#include "block.h" | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
static int DentryOpRevalidate(struct dentry *dentry, struct nameidata *nd); | |
+#else | |
+static int DentryOpRevalidate(struct dentry *dentry, unsigned int); | |
+#endif | |
struct dentry_operations LinkDentryOps = { | |
.d_revalidate = DentryOpRevalidate, | |
@@ -58,12 +62,15 @@ struct dentry_operations LinkDentryOps = { | |
*---------------------------------------------------------------------------- | |
*/ | |
-static int | |
-DentryOpRevalidate(struct dentry *dentry, // IN: dentry revalidating | |
- struct nameidata *nd) // IN: lookup flags & intent | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
+static int DentryOpRevalidate(struct dentry *dentry, struct nameidata *nd) | |
+#else | |
+static int DentryOpRevalidate(struct dentry *dentry, unsigned int flags) | |
+#endif | |
+ | |
{ | |
VMBlockInodeInfo *iinfo; | |
- struct nameidata actualNd; | |
+ struct path actualNd; | |
struct dentry *actualDentry; | |
int ret; | |
@@ -101,7 +108,11 @@ DentryOpRevalidate(struct dentry *dentry, // IN: dentry revalidating | |
if (actualDentry && | |
actualDentry->d_op && | |
actualDentry->d_op->d_revalidate) { | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) | |
+ return actualDentry->d_op->d_revalidate(actualDentry, flags); | |
+#else | |
return actualDentry->d_op->d_revalidate(actualDentry, nd); | |
+#endif | |
} | |
if (compat_path_lookup(iinfo->name, 0, &actualNd)) { | |
diff --git linux/file.c linux/file.c | |
index d7ac1f6..c53eb6f 100644 | |
--- linux/file.c | |
+++ linux/file.c | |
@@ -38,46 +38,6 @@ typedef u64 inode_num_t; | |
typedef ino_t inode_num_t; | |
#endif | |
-/* Specifically for our filldir_t callback */ | |
-typedef struct FilldirInfo { | |
- filldir_t filldir; | |
- void *dirent; | |
-} FilldirInfo; | |
- | |
- | |
-/* | |
- *---------------------------------------------------------------------------- | |
- * | |
- * Filldir -- | |
- * | |
- * Callback function for readdir that we use in place of the one provided. | |
- * This allows us to specify that each dentry is a symlink, but pass through | |
- * everything else to the original filldir function. | |
- * | |
- * Results: | |
- * Original filldir's return value. | |
- * | |
- * Side effects: | |
- * Directory information gets copied to user's buffer. | |
- * | |
- *---------------------------------------------------------------------------- | |
- */ | |
- | |
-static int | |
-Filldir(void *buf, // IN: Dirent buffer passed from FileOpReaddir | |
- const char *name, // IN: Dirent name | |
- int namelen, // IN: len of dirent's name | |
- loff_t offset, // IN: Offset | |
- inode_num_t ino, // IN: Inode number of dirent | |
- unsigned int d_type) // IN: Type of file | |
-{ | |
- FilldirInfo *info = buf; | |
- | |
- /* Specify DT_LNK regardless */ | |
- return info->filldir(info->dirent, name, namelen, offset, ino, DT_LNK); | |
-} | |
- | |
- | |
/* File operations */ | |
/* | |
@@ -132,7 +92,7 @@ FileOpOpen(struct inode *inode, // IN | |
* and that would try to acquire the inode's semaphore; if the two inodes | |
* are the same we'll deadlock. | |
*/ | |
- if (actualFile->f_dentry && inode == actualFile->f_dentry->d_inode) { | |
+ if (actualFile->f_path.dentry && inode == actualFile->f_path.dentry->d_inode) { | |
Warning("FileOpOpen: identical inode encountered, open cannot succeed.\n"); | |
if (filp_close(actualFile, current->files) < 0) { | |
Warning("FileOpOpen: unable to close opened file.\n"); | |
@@ -166,11 +126,9 @@ FileOpOpen(struct inode *inode, // IN | |
static int | |
FileOpReaddir(struct file *file, // IN | |
- void *dirent, // IN | |
- filldir_t filldir) // IN | |
+ struct dir_context *ctx) | |
{ | |
int ret; | |
- FilldirInfo info; | |
struct file *actualFile; | |
if (!file) { | |
@@ -184,11 +142,8 @@ FileOpReaddir(struct file *file, // IN | |
return -EINVAL; | |
} | |
- info.filldir = filldir; | |
- info.dirent = dirent; | |
- | |
actualFile->f_pos = file->f_pos; | |
- ret = vfs_readdir(actualFile, Filldir, &info); | |
+ ret = iterate_dir(actualFile, ctx); | |
file->f_pos = actualFile->f_pos; | |
return ret; | |
@@ -237,7 +192,7 @@ FileOpRelease(struct inode *inode, // IN | |
struct file_operations RootFileOps = { | |
- .readdir = FileOpReaddir, | |
+ .iterate = FileOpReaddir, | |
.open = FileOpOpen, | |
.release = FileOpRelease, | |
}; | |
diff --git linux/filesystem.c linux/filesystem.c | |
index af57499..931fad0 100644 | |
--- linux/filesystem.c | |
+++ linux/filesystem.c | |
@@ -322,7 +322,7 @@ Iget(struct super_block *sb, // IN: file system superblock object | |
{ | |
VMBlockInodeInfo *iinfo; | |
struct inode *inode; | |
- struct nameidata actualNd; | |
+ struct path actualNd; | |
ASSERT(sb); | |
diff --git linux/inode.c linux/inode.c | |
index 098c94c..5991f3d 100644 | |
--- linux/inode.c | |
+++ linux/inode.c | |
@@ -35,10 +35,20 @@ | |
/* Inode operations */ | |
-static struct dentry *InodeOpLookup(struct inode *dir, | |
- struct dentry *dentry, struct nameidata *nd); | |
+ | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
+static struct dentry *InodeOpLookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); | |
static int InodeOpReadlink(struct dentry *dentry, char __user *buffer, int buflen); | |
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) | |
+#else | |
+static struct dentry *InodeOpLookup(struct inode *, struct dentry *, unsigned int); | |
+static int InodeOpReadlink(struct dentry *, char __user *, int); | |
+#endif | |
+ | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 99) | |
+static const char *InodeOpFollowlink(struct dentry *dentry, struct inode *inode, void **cookie); | |
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 99) | |
+static const char *InodeOpFollowlink(struct dentry *dentry, void **cookie); | |
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) | |
static void *InodeOpFollowlink(struct dentry *dentry, struct nameidata *nd); | |
#else | |
static int InodeOpFollowlink(struct dentry *dentry, struct nameidata *nd); | |
@@ -49,12 +59,19 @@ struct inode_operations RootInodeOps = { | |
.lookup = InodeOpLookup, | |
}; | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) | |
static struct inode_operations LinkInodeOps = { | |
+#else | |
+struct inode_operations LinkInodeOps = { | |
+#endif | |
.readlink = InodeOpReadlink, | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 99) | |
+ .get_link = InodeOpFollowlink, | |
+#else | |
.follow_link = InodeOpFollowlink, | |
+#endif | |
}; | |
- | |
/* | |
*---------------------------------------------------------------------------- | |
* | |
@@ -75,7 +92,11 @@ static struct inode_operations LinkInodeOps = { | |
static struct dentry * | |
InodeOpLookup(struct inode *dir, // IN: parent directory's inode | |
struct dentry *dentry, // IN: dentry to lookup | |
- struct nameidata *nd) // IN: lookup intent and information | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
+ struct nameidata *nd) // IN: lookup intent and information | |
+#else | |
+ unsigned int flags) | |
+#endif | |
{ | |
char *filename; | |
struct inode *inode; | |
@@ -135,7 +156,12 @@ InodeOpLookup(struct inode *dir, // IN: parent directory's inode | |
inode->i_size = INODE_TO_IINFO(inode)->nameLen; | |
inode->i_version = 1; | |
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | |
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) | |
inode->i_uid = inode->i_gid = 0; | |
+#else | |
+ inode->i_gid = make_kgid(current_user_ns(), 0); | |
+ inode->i_uid = make_kuid(current_user_ns(), 0); | |
+#endif | |
inode->i_op = &LinkInodeOps; | |
d_add(dentry, inode); | |
@@ -177,7 +203,12 @@ InodeOpReadlink(struct dentry *dentry, // IN : dentry of symlink | |
return -EINVAL; | |
} | |
- return vfs_readlink(dentry, buffer, buflen, iinfo->name); | |
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 14, 99) | |
+ return vfs_readlink(dentry, buffer, buflen, iinfo->name); | |
+#else | |
+ return readlink_copy(buffer, buflen, iinfo->name); | |
+#endif | |
+ | |
} | |
@@ -198,30 +229,51 @@ InodeOpReadlink(struct dentry *dentry, // IN : dentry of symlink | |
*---------------------------------------------------------------------------- | |
*/ | |
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 99) | |
+static const char * | |
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) | |
static void * | |
#else | |
static int | |
#endif | |
InodeOpFollowlink(struct dentry *dentry, // IN : dentry of symlink | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 99) | |
+ struct inode *inode, | |
+#endif | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 99) | |
+ void **cookie) // OUT: stores opaque pointer | |
+#else | |
struct nameidata *nd) // OUT: stores result | |
+#endif | |
{ | |
int ret; | |
VMBlockInodeInfo *iinfo; | |
if (!dentry) { | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 99) | |
+ ret = -ECHILD; | |
+#else | |
Warning("InodeOpReadlink: invalid args from kernel\n"); | |
ret = -EINVAL; | |
+#endif | |
goto out; | |
} | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 99) | |
+ iinfo = INODE_TO_IINFO(inode); | |
+#else | |
iinfo = INODE_TO_IINFO(dentry->d_inode); | |
+#endif | |
if (!iinfo) { | |
ret = -EINVAL; | |
goto out; | |
} | |
- ret = vfs_follow_link(nd, iinfo->name); | |
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 99) | |
+ return *cookie = iinfo->name; | |
+#else | |
+ nd_set_link(nd, iinfo->name); | |
+#endif | |
out: | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) | |
@@ -230,3 +282,4 @@ out: | |
return ret; | |
#endif | |
} | |
+ | |
diff --git shared/compat_namei.h shared/compat_namei.h | |
index f82dd49..c432171 100644 | |
--- shared/compat_namei.h | |
+++ shared/compat_namei.h | |
@@ -21,26 +21,40 @@ | |
#include <linux/namei.h> | |
+/* Copy-n-paste from kernel's source/fs/namei.c */ | |
+struct nameidata { | |
+ struct path path; | |
+ struct qstr last; | |
+ struct path root; | |
+ struct inode *inode; /* path.dentry.d_inode */ | |
+ unsigned int flags; | |
+ unsigned seq, m_seq; | |
+ int last_type; | |
+ unsigned depth; | |
+ struct file *base; | |
+ char *saved_names[MAX_NESTED_LINKS + 1]; | |
+}; | |
+ | |
/* | |
* In 2.6.25-rc2, dentry and mount objects were removed from the nameidata | |
* struct. They were both replaced with a struct path. | |
*/ | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) | |
-#define compat_vmw_nd_to_dentry(nd) (nd).path.dentry | |
+#define compat_vmw_nd_to_dentry(nd) (nd).dentry | |
#else | |
#define compat_vmw_nd_to_dentry(nd) (nd).dentry | |
#endif | |
/* In 2.6.25-rc2, path_release(&nd) was replaced with path_put(&nd.path). */ | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) | |
-#define compat_path_release(nd) path_put(&(nd)->path) | |
+#define compat_path_release(nd) path_put(nd) | |
#else | |
#define compat_path_release(nd) path_release(nd) | |
#endif | |
/* path_lookup was removed in 2.6.39 merge window VFS merge */ | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) | |
-#define compat_path_lookup(name, flags, nd) kern_path(name, flags, &((nd)->path)) | |
+#define compat_path_lookup(name, flags, nd) kern_path(name, flags, nd) | |
#else | |
#define compat_path_lookup(name, flags, nd) path_lookup(name, flags, nd) | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment