Skip to content

Instantly share code, notes, and snippets.

@eru
Created April 17, 2016 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eru/13baeaabe6051b08c07a79d04442e309 to your computer and use it in GitHub Desktop.
Save eru/13baeaabe6051b08c07a79d04442e309 to your computer and use it in GitHub Desktop.
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