Try the following:
chmod 000 .
perl -w -e 'use Cwd qw(abs_path); print abs_path("/"), "\n"'
It fails, because abs_path tries to chdir and come back in order to do its job -- however, it cannot come back. The problem is quite interesting for me, since I develop a tool for system administration, and the following common conditions are resulting in failure:
1. the home direcotries are on nfs
2. the user homes of the sysadmins are not readable nor executable for anybody else
3. the nfs is mounted with root_squash.
Now "su", and there you go with a directory that you cannot chdir back in...

This is also a problem for me.
This bug is duplicated in ticket 27294 and bug 4593.
I noticed that this was a problem for XS abs_path and fast_abs_path, but
not _perl_abs_path. I tested on version 3.05 of pathtools.

Here's a similar situation. Dreamhost sets /home 771, so I can't read
/home but I can cd into it. This results in abs_path() (and thus
getcwd) to fail while building perl.
The problem appears to be in _perl_abs_path(), which is why it only
effects the build before Cwd.xs has been built. It can be simulated
like so...
~/tmp$ mkdir -p home/username/foo
~/tmp$ chmod 771 home
~/tmp$ sudo chown root:staff home
~/tmp$ ls home
ls: cannot open directory home: Permission denied
~/tmp$ ls -ld home
drwxrwx--x 3 root staff 102 Dec 24 02:21 home
~/tmp$ cd home/username/foo
~/tmp/home/username/foo$ perl -MCwd -wle 'print
Cwd::abs_path(".")'/Users/schwern/tmp/home/username/foo
~/tmp/home/username/foo$ perl -MCwd -wle 'print Cwd::_perl_abs_path(".")'
opendir(./../..): Permission denied at -e line 1
This is with 5.8.8 and Cwd 3.25, 5.10.0 and Cwd 3.2501. 5.6.2 w/Cwd
2.04 and 5.5.5 w/Cwd 2.01 fail with abs_path() because it is the same
code as _perl_abs_path(). It's a very old bug.

I've figured out the basic problem. You're supposed to cheat and run a
setuid executable. IEEE even recommends it.
http://www.opengroup.org/onlinepubs/009695399/functions/getcwd.html
-------------
If a program is operating in a directory where some (grand)parent
directory does not permit reading, getcwd() may fail, as in most
implementations it must read the directory to determine the name of the
file. This can occur if search, but not read, permission is granted in
an intermediate directory, or if the program is placed in that directory
by some more privileged process (for example, login). Including the
[EACCES] error condition makes the reporting of the error consistent and
warns the application writer that getcwd() can fail for reasons beyond
the control of the application writer or user. Some implementations can
avoid this occurrence (for example, by implementing getcwd() using pwd,
where pwd is a set-user-root process), thus the error was made optional.
Since this volume of IEEE Std 1003.1-2001 permits the addition of other
errors, this would be a common addition and yet one that applications
could not be expected to deal with without this addition.
-------------
So that pretty much boils down to if the opendir() fails it should fall
back to _backtick_pwd().

Attached is a fix. It just calls _backtick_pwd() if the opendir()
fails. This is, alas, a bit Unix centric but then again so are
filesystem permissions.
It might make sense to check the exact errno returned from opendir (ie.
EACCES) or to see if the directory in question is unreadable, but I
don't think it's necessary to get too specific and trying the native pwd
on failure seems a good general recovery mechanism.
The fix is still evolving. In particular I need to check when the cwd
itself is unreadable, I think all the stats in _perl_abs_path() will be
trouble.
In the process of fixing this I discovered another problem with
_perl_abs_path. realpath (which is abs_path) should work even when
given a subdir that doesn't exist and _perl_abs_path doesn't. I'll post
that in another bug, in this test it's inside a TODO.

Ok, so that's not a fix for this problem, it's a fix for a different
problem.
The XS version of abs_path() is failing if it has no rights for the
current directory. Ironicly, the _perl_abs_path() works.
Anyhow, abs_path() uses the copy of OpenBSD's realpath() in Cwd.xs.
That's code over 9 years old. On a hunch I grabbed the latest version
and slapped it in.
http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/realpath.c
As it doesn't use chdir(), and no gotos, it required a lot less
modification. This fixes the problem with abs_path() and probably a
small pile of others.
Since this version of realpath() is a lot easier to follow than the old
one, I can probably duplicate it in _perl_abs_path(). More to come, but
the latest patch is attached.

Excellent, I like the way this is going.
I applied the patch and all previous tests pass; for the new t/abs_path.t, tests 1-2 & 9-11 fail,
`pwd` says "permission denied".
Weird that they don't use fchdir() anymore, I haven't looked over the new algorithm but I
thought that would be a part of it.
-Ken

Those tests are still failing and I haven't had the time to look into why. For the last couple
releases, there have been some urgent things necessitating other fixes to be pushed out, so I've
just removed t/abs_path.t from the MANIFEST. If we can get it working, great.
-Ken

Turns out it's failing because /bin/pwd on OS X fails in this situation too:
% mkdir -p t/x_but_no_r/testdir/subdir
% chmod 100 t/x_but_no_r
% cd t/x_but_no_r/testdir
% /bin/pwd
pwd: : Permission denied
The built-in zsh command 'pwd' succeeds, but of course we can't use that. The closest we can
get is something like the $ENV{PWD} memory we get with Cwd's chdir() thingy.
-Ken