This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
The Crazy Phoenix's profile picture

Modify FS Root in an Unrevertable Way

Started by The Crazy Phoenix, 16 June 2015 - 04:00 PM
The Crazy Phoenix #1
Posted 16 June 2015 - 06:00 PM
Assume I were programming an OS, and I wanted to change the root directory. I could do this by overwriting all FS API functions. However, this can be bypassed by another program.

Thought of but invalid solutions:
  • Overwrite functions. Bypass Method: Mentioned earlier.
  • Make a local function performing all the changes and overwrite the global one to call the local one. Bypass Method: Append "../" to the start of the file name string.
  • Load it into executed programs as an environment variable. Bypass Method: Overwrite and then run shell.
Please no solutions involving rom modifications.
Creator #2
Posted 16 June 2015 - 09:32 PM
Well, do this:

path = string.find(newroot,fs.combine(newroot,path)) and fs.combine(newroot,path) or newroot

That way you'll be sure they aint bypassing anything.
valithor #3
Posted 16 June 2015 - 09:50 PM
Well, do this:

path = string.find(newroot,fs.combine(newroot,path)) and fs.combine(newroot,path) or newroot

That way you'll be sure they aint bypassing anything.

Unfortunately that line of code will always return newroot. Seeing as string.find(newroot,fs.combine(newroot,path)) will always return nil only time it wouldn't is if path was "", which would still make the line of code return newroot.

You will want to overwrite all of the fs functions following roughly the same format.

-- example of fs.open
local oldOpen = fs.open
local combine = fs.combine
newroot = "this/is/a/file/path/to/the/new/root"

fs.open = function(path,...)
  -- you would likely want checks here to make sure path is a string.
  path = combine(newroot,path)
  local s,e = path:find(newroot)
  path = e and e<=#newroot and path or combine(newroot,path)
  return oldOpen(path,...)
end



edit:
Now that I look back on this I noticed another thing I should fix.


local oldOpen = fs.open
local combine = fs.combine
local lType = type
local err = error
newroot = "this/is/a/file/path/to/the/new/root"

fs.open = function(path,...)
  if lType(path) == "string" then
	path = combine("/",path) --# gets rid of all the ".."'s
	path = combine(newroot,path)
	return oldOpen(path,...)
  else
	err("Expected String, String")
  end
end
Edited on 17 June 2015 - 01:51 AM
Creator #4
Posted 16 June 2015 - 09:55 PM
path could be "&#46;&#46;/i/am/at/the/real/root" – these ".." make it go up a dir.
valithor #5
Posted 16 June 2015 - 09:57 PM
path could be "&#46;&#46;/i/am/at/the/real/root" – these ".." make it go up a dir.

fs.combine automatically handles ".."'s

edit:

and now I said that I noticed i messed up lol I will fix it a sec.
Edited on 16 June 2015 - 07:58 PM
The Crazy Phoenix #6
Posted 16 June 2015 - 11:28 PM
I mentioned that solution in the first post and said that it could be bypassed using ".."

Maybe I could remove all preceding ".." components or error if they're there…
MKlegoman357 #7
Posted 16 June 2015 - 11:56 PM
Like valithor already mentioned, fs.combine deals with "..", a single fs.combine( rootPath, userGivenPath ) is enough.
valithor #8
Posted 17 June 2015 - 03:41 AM
I mentioned that solution in the first post and said that it could be bypassed using ".."

Maybe I could remove all preceding ".." components or error if they're there…

The one I posted deals with the ".."'s. The first time it calls fs.combine it combines the root and the path, which gets rid of all of the ".."'s. The only problem is at this point it could be at a higher point in the root directory than you want them to, so that is what the second combine call is for. It checks to see if the new root path is even in the path anymore and if it isn't it adds it back.

Even if you did remove them or error if they are there, nothing says they have to be at the beginning.
"&#46;&#46;/hi" would go up a directory, but so would: "/hi/&#46;&#46;/&#46;&#46;/hi"

I urge you to at least try out the code I posted. I am fairly certain you won't be able to break out of the new root with it.

Like valithor already mentioned, fs.combine deals with "..", a single fs.combine( rootPath, userGivenPath ) is enough.

Unfortunately a single fs.combine call leaves open the possibility of them getting out of the new root.

Example:

fs.combine("this/is/the/new/root","&#46;&#46;/&#46;&#46;/&#46;&#46;/&#46;&#46;/hi")
This would return "/hi" instead of "this/is/the/new/root/hi", which wouldn't be what he is wanting.

That is why I had two combine calls in my example. One to get rid/handle all of the ..'s and then the second one to actually add the new root.
Edited on 17 June 2015 - 01:52 AM
The Crazy Phoenix #9
Posted 17 June 2015 - 01:02 PM
Wow thank you for the great solution, I'll try it in a minute…

Edit: Shouldn't I also overwrite _G.fs[func] to prevent bypassing?
Edited on 17 June 2015 - 11:04 AM
flaghacker #10
Posted 17 June 2015 - 02:38 PM
Wow thank you for the great solution, I'll try it in a minute…

Edit: Shouldn't I also overwrite _G.fs[func] to prevent bypassing?

No, you don't need to overwrite stuff in _G explicitly. When you modify fs, you're actually modifying _G.fs .
The Crazy Phoenix #11
Posted 17 June 2015 - 06:08 PM
It turns out that valithor's solution doesn't quite work. I will post on Pastebin a functional function (lol) and comment a few details soon.
ardera #12
Posted 17 June 2015 - 06:54 PM

local newpath = fs.combine(root, fs.combine("/", path))
First it takes away the preceeding up-directory indexes (fs.combine("/", "&#46;&#46;/hey") -> "hey), and then it combines the safe path with the root. Should work.
Edited on 17 June 2015 - 04:56 PM
The Crazy Phoenix #13
Posted 17 June 2015 - 07:05 PM
It doesn't take away the preceeding up-directory indexes, that's the problem.
MKlegoman357 #14
Posted 17 June 2015 - 07:57 PM
Please post an example of code which does not work.
The Crazy Phoenix #15
Posted 17 June 2015 - 08:02 PM
Just look at the code valithor posted (the two fs.combine lines). I can't currently poste code snippets because of a forum bug I'm experiencing.
MKlegoman357 #16
Posted 17 June 2015 - 08:04 PM
You can simply press the top-left button in the editor to go to the "editing mode", in which nothing gets messed up.

EDIT: I think I know what you mean. For some reason doing:


fs.combine("", ",,/path") --> ",,/path" # for some reason the forums doesn't let me use dots, so pretend that commas are dots..

simply returns the path. That's strange, I don't really remember fs.combine acting like this..
Edited on 17 June 2015 - 06:11 PM
valithor #17
Posted 18 June 2015 - 01:38 AM
Interesting I did not remember fs.combine working that way either, but either way it is a relatively simple fix.


local oldOpen = fs.open
local combine = fs.combine
local lType = type
local err = error
newroot = "this/is/a/file/path/to/the/new/root"

fs.open = function(path,...)
  if lType(path) == "string" then
		path = combine("/",path):gsub("%.%./?","") --# gets rid of all the ".."'s
		path = combine(newroot,path)
		return oldOpen(path,...)
  else
		err("Expected String, String")
  end
end

The gsub just removes any extra "&#46;&#46;/"'s that might be present, since at that point there shouldn't be any anyway.
Edited on 17 June 2015 - 11:39 PM
The Crazy Phoenix #18
Posted 18 June 2015 - 02:16 PM
Thank you to all who helped!