Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and return PermissionDenied error when not root #5

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

jpittis
Copy link

@jpittis jpittis commented Jan 19, 2019

As discussed in #4, the current implementation does not return an error when the process does not have permission to use iptables.

Fortunately, iptables returns a special status code for permission errors:

$ sudo iptables --list foobar; echo $?
iptables: No chain/target/match by that name.
1
$ iptables --list; echo $?
Fatal: can't open lock file /run/xtables.lock: Permission denied
4

This patch does three things:

  1. Adds the PermissionDenied error.
  2. Maps an exit status of 4 to a PermissionDenied error.
  3. Runs rustfmt.

I can see why the maintainers might not like 3). The reformat diff is pretty small so I didn't revert it. If you'd like me to revert it and or patch it in a separate commit, please ask.

Finally, I didn't add any tests to this patch. Likely the code that tests this will need to be run without sudo to trigger the PermissionDenied path. I'm not sure of the nicest way to do this so I was going to wait for the maintainers to discuss.

Thanks!

@yaa110
Copy link
Owner

yaa110 commented Jan 19, 2019

Thank you for the contribution.
Please reformat the code in a separated commit.
I think, the library should return an error with non-zero values of status codes, rather than translating the status code of 4 to "Permission denied". So, the client could decide how to handle exceptions.

src/lib.rs Outdated Show resolved Hide resolved
@jpittis jpittis force-pushed the jpittis/permission-denied branch from 038ee7a to ffcd436 Compare January 20, 2019 16:03
@jpittis
Copy link
Author

jpittis commented Jan 20, 2019

I can see why you'd rather the caller interpret the exit status.

ffcd436 adds a BadExitStatus error. I haven't updated any of the tests yet. Because a non-zero exit status is now being returned as an error, this means that for most of the methods that previously returned bool, will now only return true. Therefore I've re-written their types from bool to unit.

This would be very much so a breaking change. What do you think of this approach?

@jpittis
Copy link
Author

jpittis commented Jan 20, 2019

I'm starting to see that this is a more complex change than I originally expected.

For example, on my system when I attempt to check the existence of a rule that does not exist for a chain that does not eixst:

$ sudo iptables -C INPUT -j MY_INPUT; echo $?
iptables v1.8.2 (legacy): Couldn't load target `MY_INPUT':No such file or directory

Try `iptables -h' or 'iptables --help' for more information.
2

But if we try to check for the rule that does not exist for a chain that does exist:

$ sudo iptables -C INPUT -j MY_INPUT; echo $?
iptables: No chain/target/match by that name.
1

I'm going to keep on trying to understand this behavior better before continuing with this PR.

Before when the exit status was reported as a bool, callers were
unable to distinguish between permission denied failures and
whether or not a given rule exists. Now we use an error to represent
a non-zero exit status and a bool to represent business logic like
existence.
@jpittis jpittis force-pushed the jpittis/permission-denied branch from ffcd436 to bfc634d Compare January 20, 2019 18:42
Copy link
Owner

@yaa110 yaa110 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor return values like the example I provided as comment

src/lib.rs Outdated
match self.run(&["-t", table, "-F"]) {
Ok(output) => Ok(output.status.success()),
Ok(_) => Ok(()),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.run(&["-t", table, "-F"]).and_then(|_| Ok(()))

@@ -417,6 +420,10 @@ impl IPTables {
};
}

Ok(output)
match output.status.code() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

output.status.code().and_then(|i| if i == 0 { Ok(output) } else { Err(IPTError::BadExitStatus(i)) })

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK this is invalid: and_then return type Option.

@Ulrar
Copy link

Ulrar commented Apr 26, 2019

Is this still being worked on ? I was also surprised to see my program "work" without any errors when ran as a regular user.

@jpittis
Copy link
Author

jpittis commented Apr 29, 2019

I've abandoned this so it's not currently being worked on. Might have time to work on it this weekend.

Copy link
Author

@jpittis jpittis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had some time to look at this again. Wondering if we may want to preserve IPTResult<bool> instead of IPTResult<()> in some cases. Thoughts?

Things for sure left to do:

  • Update doc comments to express new API.

Ok(output) => Ok(output.status.success()),
Err(err) => Err(err),
}
pub fn insert(&self, table: &str, chain: &str, rule: &str, position: i32) -> IPTResult<()> {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example where the result type should maybe be IPResult<bool> instead. Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants